Opened 15 years ago
Closed 13 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)
Change History (10)
by , 15 years ago
| Attachment: | changes.diff added |
|---|
follow-up: 4 comment:1 by , 15 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 , 15 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 , 15 years ago
| Patch needs improvement: | set |
|---|---|
| Triage Stage: | Unreviewed → Design 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.
comment:4 by , 15 years ago
| milestone: | 1.3 → 2.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 , 14 years ago
| Severity: | → Normal |
|---|---|
| Type: | → New feature |
comment:5 by , 13 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
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.
Code and documentation patch