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:
parent
b114fecfe4
commit
2b426635aa
@ -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):
|
||||
|
@ -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
|
||||
-----------------------
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user