Opened 14 years ago

Closed 12 years ago

#14018 closed New feature (wontfix)

Introduce class_plural %-substitution placeholder for related_name of ForeignKey/ManyToManyField

Reported by: Xiao Di Guan Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: related_name, ManyToManyField, ForeignKey, abstract base class
Cc: Triage Stage: Design decision needed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Django 1.2 introduced two %-substitution placeholders, %(class)s and %(app_label)s, to work around uniqueness issues when a custom related_name for a ForeignKey or ManyToManyField defined in an abstract base class is inherited by multiple child classes.

Quoting from Django's models documentation, "It's suggested ![...] that the name of a ManyToManyField ![...] be a plural describing the set of related model objects." Given the nature of a ManyToManyField, it may be preferable to reciprocate this pluralized field naming style through related_name. By introducing a third %-substitution placeholder, %(class_plural)s, this can be accomplished.

Consider the following snippet:

class Tag(models.Model):
    slug = models.SlugField(max_length=63, unique=True)

class Post(models.Model):
    slug = models.SlugField(max_length=127, unique=True)
    tags = models.ManyToManyField(Tag, related_name='%(class_plural)s') # docs suggest related_name='%(app_label)s_%(class)s_related'
    
    class Meta:
        abstract = True

class Entry(Post):
    title = models.CharField(max_length=255)
    content = models.TextField()
    
    class Meta:
        verbose_name_plural = 'entries'

class Event(Post):
    summary = models.CharField(max_length=255)
    start_date = models.DateTimeField()

Arguably, tag.entries and tag.events are more semantic than either tag.entry_set and tag.event_set or tag.appname_entry_related and tag.appname_event_related.

Ultimately, the introduction of a %(class_plural)s %-substitution placeholder provides greater flexibility when designing models with abstract base classes and ForeignKeys or ManyToManyFields.

Attachments (1)

changes.diff (2.5 KB ) - added by Xiao Di Guan 14 years ago.
Code and documentation patch

Download all attachments as: .zip

Change History (10)

by Xiao Di Guan, 14 years ago

Attachment: changes.diff added

Code and documentation patch

comment:1 by anonymous, 14 years ago

I don't think using verbose_name_plural as part of the related_name is a good idea. If you have a model named SpecialEntry, the default verbose_name will be 'special entry' and verbose_name_plural will be 'special entrys'.

comment:2 by Matthias Kestenholz, 14 years ago

Making code (attribute names) dependent on the result of a translation is quite a stupid idea. verbose_name_plural might evaluate to other translations depending on settings.LANGUAGE_CODE, might contain special chars and whitespace and isn't suitable at all for naming class attributes (i.e. related_name).

I'm quite sure this is "wontfix" material.

comment:3 by Łukasz Rekucki, 14 years ago

Patch needs improvement: set
Triage Stage: UnreviewedDesign decision needed

The patch "as is" surely needs improvement. A simple solution that comes to mind would be adding name_plural to Meta. Then %(class_plural) could be replaced with that value or with class' name with an "s" added. The example above would then look something like this:

class Tag(models.Model):
    slug = models.SlugField(max_length=63, unique=True)

class Post(models.Model):
    slug = models.SlugField(max_length=127, unique=True)
    tags = models.ManyToManyField(Tag, related_name='tagged_%(class_plural)s')
    
    class Meta:
        abstract = True

class Entry(Post):
    title = models.CharField(max_length=255)
    content = models.TextField()
    
    class Meta:
        name_plural = "entries" # related attribute will be "tagged_entries"
        verbose_name_plural = _("Journal entries")        

class Event(Post):
    summary = models.CharField(max_length=255)
    start_date = models.DateTimeField()
    # related attribute will be "tagged_events"

I don't think much people care about this that much, so it's mostly a "nice to have" feature.

in reply to:  1 comment:4 by Xiao Di Guan, 14 years ago

milestone: 1.32.0

Replying to anonymous and mk:
Good point; I hadn't considered verbose_name_plurals with multiple and/or internationalised words.

Replying to lrekucki:
That's a rather elegant solution. I agree that it's more of a nice touch than a must-have feature, but I make use of this patch in my code, and don't believe there's any harm in including it.

Thanks for all the suggestions! I'm presently working on a patch with updated documentation and a set of test cases.

comment:5 by Julien Phalip, 14 years ago

Severity: Normal
Type: New feature

comment:6 by Jacob, 13 years ago

Milestone 2.0 deleted

comment:3 by Aymeric Augustin, 13 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:4 by Aymeric Augustin, 13 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:5 by Aymeric Augustin, 12 years ago

Resolution: wontfix
Status: newclosed

I'm going to close this ticket, because it proposes to hardcode one specific case, rather than provide an API to resolve the general problem.

There are several other tickets about related name with more general proposals.

Note: See TracTickets for help on using tickets.
Back to Top