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 import connection, transaction
|
||||||
from django.db.models import signals, get_model
|
from django.db.models import signals, get_model
|
||||||
from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, get_ul_class
|
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)
|
add_lazy_relation(cls, self, other)
|
||||||
else:
|
else:
|
||||||
self.do_related_class(other, cls)
|
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):
|
def set_attributes_from_rel(self):
|
||||||
self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
|
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
|
raise TypeError, "Related Field has invalid lookup: %s" % lookup_type
|
||||||
|
|
||||||
def _get_related_query_name(self, opts):
|
def _get_related_query_name(self, opts):
|
||||||
# This method defines the name that can be used to identify this related object
|
# This method defines the name that can be used to identify this
|
||||||
# in a table-spanning query. It uses the lower-cased object_name by default,
|
# related object in a table-spanning query. It uses the lower-cased
|
||||||
# but this can be overridden with the "related_name" option.
|
# object_name by default, but this can be overridden with the
|
||||||
|
# "related_name" option.
|
||||||
return self.rel.related_name or opts.object_name.lower()
|
return self.rel.related_name or opts.object_name.lower()
|
||||||
|
|
||||||
class SingleRelatedObjectDescriptor(object):
|
class SingleRelatedObjectDescriptor(object):
|
||||||
|
@ -886,6 +886,10 @@ relationship should work. All are optional:
|
|||||||
`related objects documentation`_ for a full
|
`related objects documentation`_ for a full
|
||||||
explanation and example.
|
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
|
``to_field`` The field on the related object that the relation
|
||||||
is to. By default, Django uses the primary key of
|
is to. By default, Django uses the primary key of
|
||||||
the related object.
|
the related object.
|
||||||
@ -893,6 +897,8 @@ relationship should work. All are optional:
|
|||||||
|
|
||||||
.. _`Database API reference`: ../db-api/
|
.. _`Database API reference`: ../db-api/
|
||||||
.. _related objects documentation: ../db-api/#related-objects
|
.. _related objects documentation: ../db-api/#related-objects
|
||||||
|
.. _abstract base class: `Abstract base classes`_
|
||||||
|
.. _extra notes: `Be careful with related_name`_
|
||||||
|
|
||||||
Many-to-many relationships
|
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 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.
|
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
|
Multi-table inheritance
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user