Shuvam Jaswal
Shuvam Jaswal

Reputation: 47

Django: Linking Models in different apps gives circular import error

I have two apps in my project names quiz_app_teacher and accounts many models from these files are connected with each other, but when i try to migrate I get this error

File "F:\self\quiz_site\quiz_app_teacher\models.py", line 2, in from accounts import models as account_models File "F:\self\quiz_site\accounts\models.py", line 13, in class Student(models.Model): File "F:\self\quiz_site\accounts\models.py", line 15, in Student quizzes = models.ManyToManyField(quiz_models.Quiz) AttributeError: partially initialized module 'quiz_app_teacher.models' has no attribute 'Quiz' (most likely due to a circular import)

quiz_app_teacher/models.py

from django.utils import timezone 
from accounts import models as account_models
from django.db import models
# Create your models here.
ANSWER_CHOICES = (
   ('A', 'A'),
   ('B', 'B'),
   ('C','C'),
   ('D','D'),
)
class Quiz(models.Model):
    #https://www.sankalpjonna.com/learn-django/the-right-way-to-use-a-manytomanyfield-in-django
    name=models.CharField(max_length=250)
    quiz_id = models.CharField(max_length=300,)
    created_date = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(account_models.User, on_delete=models.CASCADE,related_name='quizzes')
    #Using related_names Author.quizzes.all()
    #will list all the quizzes which are made by that author.
    course = models.ForeignKey(account_models.Course, on_delete=models.CASCADE, related_name='quizzes')

    def save(self, *args, **kwargs):
        #override default save method to do something before saving object of model
        if not self.quiz_id:
            self.quiz_id = self.name+"-"+self.created_date.strftime("%M%S")  #TODO:Edit this 
        super(Quiz, self).save(*args, **kwargs)
    def __str__(self):
        return self.name 

class result(models.Model):
    #quiz=models.OneToOneField(Quiz,on_delete=models.CASCADE)
    student=models.ForeignKey(account_models.Student , on_delete=models.CASCADE,related_name='my_results')#maybe use account_models.User
    quiz=models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='results')
    points=models.IntegerField()
    def __str__(self):
        return  f"Student name: { str(self.student)} Points:{ str(self.points)}"


class Question(models.Model):
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='questions')
    #quiz=models.ForeignKey(Quiz, on_delete=models.CASCADE)
    question=models.CharField(max_length=300,)
    A = models.CharField(max_length=200,)
    B = models.CharField(max_length=200,)
    C = models.CharField(max_length=200,)
    D = models.CharField(max_length=200,)
    answer = models.CharField(max_length=200,choices=ANSWER_CHOICES,default='A')
    question_number=models.IntegerField()
    def __str__(self):
        return self.question

accounts/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models
import quiz_app_teacher.models as quiz_models
# Create your models here.
class Course(models.Model):
    name = models.CharField(max_length=30)
    Year=models.IntegerField()
    def __str__(self):
        return self.name
class User(AbstractUser):
    is_teacher = models.BooleanField(default=False)
class Student(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    quizzes = models.ManyToManyField(quiz_models.Quiz)
    course  = models.ForeignKey(Course,on_delete=models.CASCADE, related_name='class_students')
    def __str__(self):
        return self.user.username
class Teacher(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    quizzes = models.ManyToManyField(quiz_models.Quiz)
    def __str__(self):
        return self.user.username

If i try to define relations using

quizzes = models.ManyToManyField(to='quiz_models.Quiz')

SystemCheckError: System check identified some issues:

ERRORS: accounts.Student.quizzes: (fields.E300) Field defines a relation with model 'quiz_models.Quiz', which is either not installed, or is abstract. accounts.Student.quizzes: (fields.E307) The field accounts.Student.quizzes was declared with a lazy reference to 'quiz_models.quiz', but app 'quiz_models' isn't installed. accounts.Student_quizzes.quiz: (fields.E307) The field accounts.Student_quizzes.quiz was declared with a lazy reference to quiz_models.quiz', but app 'quiz_models' isn't installed.

Upvotes: 1

Views: 533

Answers (1)

0sVoid
0sVoid

Reputation: 2663

You can remove your imports and refer to your ForeignKey models like so:

models.ForeignKey('account_models.Course', ...)

This should allow you to run your migrations without a circular import

https://docs.djangoproject.com/en/4.0/ref/models/fields/#django.db.models.ForeignKey

Edit from OP:

Update: I fixed it by running migrations for both files simultaneously. python manage.py makemigrations accounts quiz_app_teacher

Upvotes: 2

Related Questions