Error inheriting an abstract class with foreign keys

I have the code below written in django

from django.db import models from django.contrib.auth.models import User class AuditColumns(models.Model): created_at=models.DateField("Created at") created_by=models.ForeignKey(User, db_column="created_by", related_name="poll_user_created_by") updated_at=models.DateTimeField("Updated at") updated_by=models.ForeignKey(User, db_column="updated_by", null=True, related_name="poll_user_updated_by") class Meta: abstract = True class Poll(AuditColumns): question=models.CharField(max_length=300) start_poll_at=models.DateTimeField(null=True) end_poll_at=models.DateTimeField(null=True) is_active=models.BooleanField(default=True) class Choice(AuditColumns): choice=models.CharField(max_length=200) 

when I execute this code I get the following error

 mo@debian :~/PycharmProjects/KlamTam$ ./manage.py sql polls Error: One or more models did not validate: polls.poll: Accessor for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'. polls.poll: Reverse query name for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'. polls.poll: Accessor for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'. polls.poll: Reverse query name for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'. polls.choice: Accessor for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'. polls.choice: Reverse query name for field 'created_by' clashes with related field 'User.poll_user_created_by'. Add a related_name argument to the definition for 'created_by'. polls.choice: Accessor for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'. polls.choice: Reverse query name for field 'updated_by' clashes with related field 'User.poll_user_updated_by'. Add a related_name argument to the definition for 'updated_by'. 

This has to do with setting a unique sibling_name, is there a way to dynamically generate related names to make sure they are always unique? Of course, it would be better to know what the link_name is related to and, if possible, not to set them?

Hello,

+4
source share
1 answer

Related names are provided by Django ORM so you can easily find all the models that are part of the current model. Therefore, if you have a key to Foo to Bar, the Bar instance will default to the foo_set attribute, which will provide you with a list of all the Foos associated with this particular bar.

You can specify your own connection_name to make the code easier to read, with more natural / relevant related names.

However, as you can see, Django ORM requires unique values ​​for the associated names, and since you have an FK in your base class, it automatically creates these FKs for all child models and uses the same name for them, which is not viable .

Good news: this documentation note shows a workaround for Django 1.2+

If for some reason you need to use Django 1.1 or earlier, here is an alternative solution: instead of using FK in the abstract model, just use the pk storage field for the model with keys and add accessors accordingly. eg:

 class AuditBase(models.Model): created_at = models.DateTimeField("Created at", auto_now_add=True) created_by = models.IntegerField(required=True) updated_at = models.DateTimeField("Updated at", auto_now=True) updated_by = models.IntegerField(required=True) class Meta: abstract = True @property def creator(self): return User.objects.get(id=self.created_by) @property def last_editor(self): return User.objects.get(id=self.updated_by) def save(self, *args, **kwargs): #track the creator/last editor via an optional kwarg active_user = self.kwargs.get('user') if active_user: self.updated_by = active_user if active_user and not self.created_by: self.created_by = active_user return super(AuditBase, self).save(*args, **kwargs) 
+8
source

Source: https://habr.com/ru/post/1332669/


All Articles