1
0
mirror of https://github.com/django/django.git synced 2025-07-05 18:29:11 +00:00

queryset-refactor: Added a way to specify the related_name attribute on

abstract base classes.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7432 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-04-16 08:09:46 +00:00
parent b114fecfe4
commit 2b426635aa
2 changed files with 47 additions and 3 deletions

View File

@ -1,3 +1,5 @@
import copy
from django.db import connection, transaction
from django.db.models import signals, get_model
from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, get_ul_class
@ -108,6 +110,8 @@ class RelatedField(object):
add_lazy_relation(cls, self, other)
else:
self.do_related_class(other, cls)
if not cls._meta.abstract and self.rel.related_name:
self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
def set_attributes_from_rel(self):
self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
@ -149,9 +153,10 @@ class RelatedField(object):
raise TypeError, "Related Field has invalid lookup: %s" % lookup_type
def _get_related_query_name(self, opts):
# This method defines the name that can be used to identify this related object
# in a table-spanning query. It uses the lower-cased object_name by default,
# but this can be overridden with the "related_name" option.
# This method defines the name that can be used to identify this
# related object in a table-spanning query. It uses the lower-cased
# object_name by default, but this can be overridden with the
# "related_name" option.
return self.rel.related_name or opts.object_name.lower()
class SingleRelatedObjectDescriptor(object):

View File

@ -886,6 +886,10 @@ relationship should work. All are optional:
`related objects documentation`_ for a full
explanation and example.
If using this in an `abstract base class`_, be
sure to read the `extra notes`_ in that section
about ``related_name``.
``to_field`` The field on the related object that the relation
is to. By default, Django uses the primary key of
the related object.
@ -893,6 +897,8 @@ relationship should work. All are optional:
.. _`Database API reference`: ../db-api/
.. _related objects documentation: ../db-api/#related-objects
.. _abstract base class: `Abstract base classes`_
.. _extra notes: `Be careful with related_name`_
Many-to-many relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -2146,6 +2152,39 @@ abstract base class. For example, including ``db_table`` would mean that all
the child classes (the ones that don't specify their own ``Meta``) would use
the same database table, which is almost certainly not what you want.
Be careful with ``related_name``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are using the ``related_name`` attribute on a ``ForeignKey`` or
``ManyToManyField``, you must always specify a *unique* reverse 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``) each time.
To work around this problem, when you are using ``related_name`` in an
abstract base class (only), part of the name should be the string
``'%(class)s'``. This is replaced by the lower-cased name of the child class
that the field is used in. Since each class has a different name, each related
name will end up being different. For example::
class Base(models.Model):
m2m = models.ManyToMany(OtherModel, related_name="%(class)s_related")
class Meta:
abstract = True
class ChildA(Base):
pass
class ChildB(Base):
pass
The reverse name of the ``ChildA.m2m`` field will be ``childa_related``,
whilst the reverse name of the ``ChildB.m2m`` field will be
``childb_related``. It is up to you how you use the ``'%(class)s'`` portion to
construct your related name, but if you forget to use it, Django will raise
errors when you validate your models (or run ``syncdb``).
Multi-table inheritance
-----------------------