[Django]-M2m 'through' field in django models throwing this error: 'M2M field' object has no attribute '_m2m_reverse_name_cache'

2πŸ‘

βœ…

The way you have defined your models the queries seem too confusing. Try how models are defined below and then try the query.

You did not mention the through_field attribute in the many to many field definition. check the docs: https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ManyToManyField

class Department(models.Model):
    # i think this is not needed. Also id is a protected keyword in python.
    # id                  = models.BigAutoField(primary_key=True)
    user                = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    assistants          = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Assistants', 
                                                 related_name='departments', through_fields=("department", "assistant"))

# model name should never be prural. It is singluar becuase it is the name of the object.
class Assistant(models.Model):
    # i think this is not needed. Also id is a protected keyword in python.
    # id                  = models.BigAutoField(primary_key=True)
    department          = models.ForeignKey(Department, on_delete=models.CASCADE)
    assistant           = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name="Department Assistant", on_delete=models.CASCADE)
    added               = models.DateTimeField(auto_now_add=True)


# how to query assistants from departments
# you will get objects of User model
qs = department.assistants.all()


# how to query departments from assistants
# you will get objects of Department model
qs = user.departments.all()


# If you want to query the Assistant model

# from department object
qs = department.assistant_set.all()

# from assistant object
qs = user.assistant_set.all()

# in either case you will get the objects of Assistant model
for i in qs:
    print(i.added, i.department, i.assistant)

Try this and let me know if you still get the error.

My suggestion is to name the assistant field on the Assistant model as user. This way you will not need to define through_field on the many to many field.

πŸ‘€zaphod100.10

1πŸ‘

If one assistant relates to only one department – this is relation one-to-many. (One department has many assistants) In code would be:

class Assistant(models.Model):
    ...
    department = models.ForeignKey(Department)

No need for a special reference on Department. To get all assistants:

assistants = models.Assistant.objects.filter(department=department)

Or create a property on a class Department:

@property
def assistants(self):
    return models.Assistant.objects.filter(department=self)

If one assistant relates to many departments (and each department has many assistants), it is many-to-many relationship and there should be additional class between them:

class Assignment(models.Model):
    assistant = models.ForeignKey(Assistant)
    department = models.ForeignKey(Department)

class Department(models.Model):
    ...
    assignment= models.ForeignKey(Assignment)

class Assistant(models.Model):
    ...
    assignment = models.ForeignKey(Assignment)

So here to query assistants of the department:

assistants = models.Assistant.objects.filter(
    assignment__in=models.Assignment.objects.filter(
        department=department
    )
)
πŸ‘€Egor Wexler

Leave a comment