JasonGenX
JasonGenX

Reputation: 5434

Django 1.11: Can't get ManyToManyField to work

I have the following models:

class Address(models.Model):   
    address1 = models.CharField(max_length=150, null=True)
    address2 = models.CharField(max_length=150, null=True, blank=True)
    city = models.CharField(max_length=50, null=True)
    state_province = models.CharField(max_length=50, null=True)
    zipcode = models.CharField(max_length=10, null=True)
    country = models.CharField(max_length=3, default='USA', null=False)
    created_at = models.DateTimeField(db_index=True, auto_now_add=True)
    updated_at = models.DateTimeField(db_index=True, auto_now=True)

    class Meta:
        db_table = 'addresses'

and this one.....

class User(models.Model, AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(db_index=True, max_length=150, unique=True,
                              null=False)
    first_name = models.CharField(max_length=45, null=False)
    last_name = models.CharField(max_length=45, null=False)
    mobile_phone = models.CharField(max_length=12, null=True)
    profile_image = models.CharField(max_length=150, null=True)
    is_staff = models.BooleanField(db_index=True, null=False, default=False)
    is_active = models.BooleanField(
        _('active'),
        default=True,
        db_index=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )

    addresses = models.ManyToManyField(Address),


    USERNAME_FIELD = 'email'
    objects = MyCustomUserManager()

    def __str__(self):
        return self.email

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

    class Meta:
        db_table = 'users'

My first mystery is that by migrating the models, there is no "addresses" field in the users table, nor a pivot table in the database to keep the multiple relationships. How are ManyToMany payloads kept??

Secondly, my goal is to have multiple addresses for Users. I want Users to have multiple "Addresses" (and not each address having one User) because other models can have addresses too. I don't want the Address model to have 12 different "owner" fields with with ForeignKeys.

So. I try this:

from myApp.models import User
from myApp.models import Address
user = User(email="[email protected]", first_name="john", last_name="doe", mobile_phone="444")
# the model permits partial address fields, don't worry about that.
address = Address(city="New York", zipcode="10014")

Now I try to add the address to the user.addresses and I'm getting an error.

user.addresses.add(address)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-0337af6b1cd4> in <module>()
----> 1 user.addresses.add(address)

AttributeError: 'tuple' object has no attribute 'add'

Help?

Upvotes: 0

Views: 216

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599490

You have a superfluous comma after the definition of the many-to-many field, which turns it into a tuple. When you've removed this, you'll find both that the migrations will create your intermediary table, and that user.addresses.add() will work.

Upvotes: 3

Related Questions