I want to create on Abstract Model class for future inheriting like this:
class AbstractModel(models.Model):
created_at = models.DateTimeField(
auto_now_add=True,
blank=True,
null=True,
)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='XXX_created_by',
blank=True,
null=True,
)
class Meta:
abstract = True
Field 'created_at' is working fine, but how to generate related_name in 'created_by' for my child classes to prevent clashing?
CodePudding user response:
As the Be careful with related_name
and related_query_name
section of the documentation says, you can:
To work around this problem, when you are using
related_name
orrelated_query_name
in an abstract base class (only), part of the value should contain'%(app_label)s'
and'%(class)s'
.
'%(class)s'
is replaced by the lowercased name of the child class that the field is used in.
'%(app_label)s'
is replaced by the lowercased name of the app the child class is contained within. Each installed application name must be unique and the model class names within each app must also be unique, therefore the resulting name will end up being different.
You thus can work with:
class AbstractModel(models.Model):
# …
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='%(class)s_created_by',
blank=True,
null=True,
)
class Meta:
abstract = True
Then the related_name
will be foo_created_by
if the name of the model that inherits is named foo
.
Or if the same model name can occur in different apps:
class AbstractModel(models.Model):
# …
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='%(app_label)s_%(class)s_created_by',
blank=True,
null=True,
)
class Meta:
abstract = True
Then the related_name
will be bar_foo_created_by
if the name of the model that inherits is named foo
in an app named bar
.