S B
S B

Reputation: 8384

Cannot add ManyToManyField objects in Django

I am unable to add ManyToManyField objects even after following the doc

models.py

class Label(models.Model):
    ...
    name = models.CharField(blank=False, max_length=100)

class Template(models.Model):
    ...
    labels = models.ManyToManyField(Label, blank=True, related_name="labels")

And then

>>> from content.models import Label, Template
>>> l1 = Label.objects.get_or_create(name='one') # saves in db
>>> l2 = Label.objects.get_or_create(name='two') # saves in db
>>> t1 = Template.objects.get(pk=1)           # loads existing
>>> t1.labels.set([l1,l2])                       # fails

throws this error

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 1007, in set 
    self.add(*new_objs)
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 934, in add 
    self._add_items(self.source_field_name, self.target_field_name, *objs)
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 1083, in _add_items
    '%s__in' % target_field_name: new_ids,
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/query.py", line 784, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/query.py", line 802, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1250, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1276, in _add_q
    allow_joins=allow_joins, split_subq=split_subq,
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1206, in build_filter
    condition = lookup_class(lhs, value)
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/lookups.py", line 24, in __init__
    self.rhs = self.get_prep_lookup()
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 56, in get_prep_lookup
    self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 56, in <listcomp>
    self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
  File "/path/env3tt/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 966, in get_prep_value
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'Label'

I am using Django 1.11 on Python 3.6.

Upvotes: 1

Views: 336

Answers (1)

solarissmoke
solarissmoke

Reputation: 31404

You are using get_or_create which returns a tuple of (object, created), not just an object.

So l1 and l2 are not Label objects as you assume, but tuples. Passing this to the many-to-many manager will not work.

Change your code as follows:

from content.models import Label, Template
# Ignore the second item returned by get_or_create
l1, _ = Label.objects.get_or_create(name='one') 
l2, _ = Label.objects.get_or_create(name='two') #
t1 = Template.objects.get(pk=1)
t1.labels.set([l1,l2]) 

Upvotes: 4

Related Questions