TypeError: int() argument must be a string or a number, not 'Model Instance'

和自甴很熟 提交于 2019-12-23 09:29:54

问题


Here's my models.py:

from django.db import models

class Location(models.Model):
   location_name = models.CharField(max_length=100)
   def __unicode__(self):
      return self.location_name

class Menu(models.Model):
   location = models.ManyToManyField(Location)
   restaurant_name = models.CharField(max_length=200)
   dish_category = models.CharField(max_length=100)
   dish_name = models.CharField(max_length=200)
   VNV_tag = models.CharField(max_length=100)
   quantity = models.CharField(max_length=10, default='FULL')
   price = models.CharField(max_length=5, default=0)
   def __unicode__(self):
       return self.restaurant_name

I am trying to populate my database from an excel file using xlrd python module. Here's my populate_db.py script:

import os
import xlrd
from menusearch.models import Menu, Location
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'midnitepro.settings')
import django
django.setup()

def populate():
    book = xlrd.open_workbook('/Users/Sahil/Desktop/MNFP1.xlsx')
    sheet = book.sheet_by_index(0)
    count1 = 0
    while count1<sheet.nrows:
        value_list = []
        count2 = 0
        while count2<sheet.ncols:
            value_list.append(sheet.row_values(count1, start_colx=count2, end_colx=count2+1))
            count2 +=1
        add_menuitem(value_list)
        count1 += 1

def add_menuitem(value_list):
    split_query = []
    m = Menu.objects.create()
    value_list = [str(x[0]).encode('utf-8') for x in value_list if x]

    m.restaurant_name = (value_list[0])
    m.dish_category = (value_list[1])
    m.dish_name = (value_list[2])
    m.VNV_tag = (value_list[3])
    m.quantity = (value_list[4])
    m.price = (value_list[5])
    # m.location.add(int(value_list[6]))

    split_query = (value_list[6]).split(",")
    for sq in split_query:
        l = Location.objects.get_or_create(location_name=sq)
        try:
            m.location.add(l)
        except ValueError:
            print "Problem Adding Location to Menu."

    m.save()

if __name__ == '__main__':
    print "Starting population script..."
    from menusearch.models import Menu, Location
    populate()

Now when I run the populate_db.py script, the output on the terminal reads: "Problem Adding Location to Menu.". I see that the problem exists here in the populate_db script: m.location.add(l) But this queryset is in line with the syntax given here: https://docs.djangoproject.com/en/1.8/topics/db/examples/many_to_many/

After removing the try/except, my traceback reads:

TypeError: int() argument must be a string or a number, not 'Location' 

Please explain what is happening here. And how to properly add a a value to the ManyToManyField via a queryset.

Possible duplicate: Django Error: TypeError: int() argument must be a string or a number, not 'BuildsTable' But I would still like to know the answer in my case as I'm using a ManyToManyField.

Full traceback:

l= (<Location: Indiranagar>, False)

Inside Loop - sq=  Indiranagar
Traceback (most recent call last):
  File "populate_db.py", line 62, in <module>
populate()
  File "populate_db.py", line 23, in populate
add_menuitem(value_list)
  File "populate_db.py", line 50, in add_menuitem
m.location.add(l)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/related.py", line 973, in add
self._add_items(self.source_field_name, self.target_field_name, *objs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1079, in _add_items
'%s__in' % target_field_name: new_ids,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 679, in filter
return self._filter_or_exclude(False, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/query.py", line 697, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1304, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1332, in _add_q
allow_joins=allow_joins, split_subq=split_subq,
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1194, in build_filter
lookups, value)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1745, in get_lookup_constraint
root_constraint.add(lookup_class(targets[0].get_col(alias, sources[0]), value), AND)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/lookups.py", line 96, in __init__
self.rhs = self.get_prep_lookup()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/lookups.py", line 134, in get_prep_lookup
return self.lhs.output_field.get_prep_lookup(self.lookup_name, self.rhs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 729, in get_prep_lookup
return [self.get_prep_value(v) for v in value]
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 985, in get_prep_value
return int(value)
TypeError: int() argument must be a string or a number, not 'Location'.

回答1:


To add a value to a ManyToManyField, you need to add the objects by passing them as arguments.

add(obj1, obj2, obj3, ...)

This will add the specified objects to the related object set.

You can call the add() like below:

menu_object.location.add(loc_obj1, loc_obj2, ...) 

In your case, you need to do:

l = Location.objects.get_or_create(location_name=sq)[0]

You need to access the instance by index 0 as get_or_create returns a tuple (instance, created). Then pass this instance to the add() method.

Note:
Using add() with a many-to-many relationship will not call any .save() for each object, but rather create the relationships using .bulk_create().




回答2:


I understand that Rahul Gupta has answered this already. But on a more theoretical level I think this is what happened when you use get_or_create here:

l = Location.objects.get_or_create(location_name=sq)

It returns a Tuple, and hence you have to call it's first element by modifying it to:

l = Location.objects.get_or_create(location_name=sq)[0]

Which returns only the index element of the tuple/dictionary!



来源:https://stackoverflow.com/questions/31348012/typeerror-int-argument-must-be-a-string-or-a-number-not-model-instance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!