razieh babaee
razieh babaee

Reputation: 298

How to set related_name in ManyToMany field in an abstract model?

I have this abstract model:

class HasSystemMessage(models.Model):
    class Meta:
        abstract = True

    messages = models.ManyToManyField(SystemMessage, related_name=?)

I am going to use this abstract model in at least three other models, lets say, A, B, and C. How can I set the related_name dynamically for these classes? for example, for class B, I want the related_name to be Bs. Is it possible to do so?

To further clarify the question, The classes will look like this:

class B(HasSystemMessage):
    # Some model fields 
class A(HasSystemMessage):
    # Some model fields

HasSystemMessage.objects.filter(a__contains=[some elements])

Upvotes: 3

Views: 1785

Answers (2)

waranlogesh
waranlogesh

Reputation: 1024

You can use %(class)s or %(app_label)s

class HasSystemMessage(models.Model):
    class Meta:
        abstract = True

    messages = models.ManyToManyField(SystemMessage, related_name=%(app_label)s_%(class)s_related)

From Django docs

Be careful with related_name and related_query_name¶ If you are using related_name or related_query_name on a ForeignKey or ManyToManyField, you must always specify a unique reverse name and query name for the field. This would normally cause a problem in abstract base classes, since the fields on this class are included into each of the child classes, with exactly the same values for the attributes (including related_name and related_query_name) each time.

To work around this problem, when you are using related_name or related_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 lower-cased name of the child class that the field is used in. '%(app_label)s' is replaced by the lower-cased 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.

Ref: https://docs.djangoproject.com/en/2.0/topics/db/models/#be-careful-with-related-name-and-related-query-name

Upvotes: 5

ans2human
ans2human

Reputation: 2357

You Just need to put a string in this attribute which specifies the name of the reverse relation from the SystemMessage.Also read in Django Docs

Try this:

class HasSystemMessage(models.Model):
class Meta:
    abstract = True

messages = models.ManyToManyField(SystemMessage, related_name='system_message')

Upvotes: 0

Related Questions