bryan.blackbee
bryan.blackbee

Reputation: 1954

Django ManyToManyField Foreign Key Design

As part of an Address Book application, I have the following in my models.py

from django.db import models

class Contact(models.Model):
    contact_id= models.AutoField(auto_created=True, primary_key=True, default=1, verbose_name='ID')
    name = models.CharField(max_length=100, unique=True)
    contact_no = models.ManyToManyField(ContactNumberTypeField, 
                 through='ContactContactNumber', through_fields=('contact_name','contact_type'))

    def __str__(self):
        return self.name

class ContactNumberTypeField(models.Model):
    contact_number_type=models.AutoField(auto_created=True, primary_key=True, default=1, verbose_name='ID')
    name = models.CharField(max_length=20)
    contact_no = models.ManyToManyField(Contact, 
                 through='ContactContactNumber', through_fields=('contact_name','contact_type'))
    def __str__(self):
        return self.name             

class ContactContactNumber(models.Model):
    contact_name=models.ForeignKey(Contact)
    contact_type=models.ForeignKey(ContactNumberTypeField)
    contact_number = models.CharField(max_length=50)

    def __str__(self):
        return contact_number

My question is that why is it when I run makemigrations, it throws a ContactNumberTypeField is not defined error?

Update

Correct code is as follows

from django.db import models

class Contact(models.Model):
    contact_id= models.ManyToManyField('ContactNumberTypeField', 
                 through='ContactContactNumber', through_fields=('contact_name','contact_type'))
    name = models.CharField(max_length=100, unique=True)


    def __str__(self):
        return self.name

class ContactNumberTypeField(models.Model):
    contact_number_type=models.ManyToManyField('Contact', 
                 through='ContactContactNumber', through_fields=('contact_type','contact_name'))
    name = models.CharField(max_length=20)
    contact_no = models.IntegerField(max_length=20)
    def __str__(self):
        return self.name             

class ContactContactNumber(models.Model):
    contact_name=models.ForeignKey(Contact)
    contact_type=models.ForeignKey(ContactNumberTypeField)
    contact_number = models.CharField(max_length=50)

    def __str__(self):
        return contact_number

Upvotes: 1

Views: 3472

Answers (1)

catavaran
catavaran

Reputation: 45555

ContactNumberTypeField is not defined at the time of defining of Contact class. Change contact_no field to this:

class Contact(models.Model):
    ...
    contact_no = models.ManyToManyField('ContactNumberTypeField', 
                 through='ContactContactNumber',
                 through_fields=('contact_name','contact_type'))

Note the quotes around 'ContactNumberTypeField'.

The other error here is the wrong order of field names in through_fields attribute of the ContactNumberTypeField.contact_no field. It should be:

class ContactNumberTypeField(models.Model):
    ...
    contact_no = models.ManyToManyField(Contact, 
                 through='ContactContactNumber',
                 through_fields=('contact_type','contact_name'))

Read the documentation about field1 and field2.

Upvotes: 2

Related Questions