Milano
Milano

Reputation: 18745

How to properly define through-model in Django

I'm facing a problem when I'm trying to define through-model in Django. I've posted a question couple hours ago and the answer was to define a through class. But the problem is, that this through-model calls already defined models and one of these models which are defined before this through-model is calling this through-model.

NameError: name 'TranslatorLanguage' is not defined

If I switch them:

NameError: name 'UserProfile' is not defined

THIS IS THE ANSWER (In fact it's not a TranslatorProfile but UserProfile)

Do you know what to do?

I'm attaching models.py in case it helps:

from __future__ import unicode_literals
# from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import User
from django.db import models

class AdminContact(models.Model):
    email = models.EmailField()
    telephone = models.CharField(max_length=40)

    def __unicode__(self):
        return self.email

class Language(models.Model):
    shortcut = models.CharField(max_length=40)
    name = models.CharField(max_length=40)

    def __str__(self):
        return self.name



class Level(models.Model):
    LEVEL_CHOICES = (
        ('standard','Standard level'),
        ('professional','Professional level'),
        ('native','Native speaker level'),
    )
    name = models.CharField(max_length=40,choices=LEVEL_CHOICES, blank=False, null=False)
    price_multiplier = models.FloatField()



class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='userprofile')
    date_of_birth = models.DateField(null=True,blank=True)
    telephone = models.CharField(max_length=40,null=True,blank=True)
    IBAN = models.CharField(max_length=40,null=True,blank=True)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)


    MARITAL_STATUS_CHOICES = (
        ('single', 'Single'),
        ('married', 'Married'),
        ('separated', 'Separated'),
        ('divorced', 'Divorced'),
        ('widowed', 'Widowed'),
    )
    marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True, blank=True)

    HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
        ('coincidence', u'It was coincidence'),
        ('relative_or_friends', 'From my relatives or friends'),
    )
    how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True,
                                                blank=True)

    # TRANSLATOR ATTRIBUTES

    is_translator = models.BooleanField(default=False)

    language_tuples = models.ManyToManyField(LanguageTuple,blank=True)
    languages = models.ManyToManyField(Language, through='TranslatorLanguage')

    rating = models.IntegerField(default=0)

    number_of_ratings = models.BigIntegerField(default=0)

    def __unicode__(self):
        return '{} {}'.format(self.user.first_name, self.user.last_name)

    def __str__(self):
        return '{} {}'.format(self.user.first_name, self.user.last_name)

class UserProfileLanguage(models.Model):
    userprofile = models.ForeignKey(UserProfile)
    language = models.ForeignKey(Language)
    level = models.ForeignKey(Level)

    class Meta:
        unique_together = (('UserProfile', 'language'),)

Upvotes: 0

Views: 409

Answers (2)

Shang Wang
Shang Wang

Reputation: 25549

You should use string of model instead of model class itself to refer to the foreign key. It's specially true when you have definition sequence problem. Quoting from django doc foreign key section:

If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself:

from django.db import models

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'Manufacturer',
        on_delete=models.CASCADE,
    )
    # ...

class Manufacturer(models.Model):
    # ...
    pass

Upvotes: 1

koniiiik
koniiiik

Reputation: 4382

You'll need to specify the TranslatorLanguage model as a string, since it is defined later in models.py, like this:

languages = models.ManyToManyField(Language, through='TranslatorLanguage')

Upvotes: 0

Related Questions