mirror of
https://github.com/django/django.git
synced 2025-10-04 07:46:37 +00:00
Fixed #17002 -- Allowed using a ManyToManyField through model that inherits another.
This commit is contained in:
parent
b5f0b3478d
commit
98359109eb
7 changed files with 147 additions and 17 deletions
|
@ -14,6 +14,7 @@ from django.db.models import Manager
|
|||
from django.db.models.fields import AutoField
|
||||
from django.db.models.fields.proxy import OrderWrt
|
||||
from django.db.models.fields.related import OneToOneField
|
||||
from django.db.models.query_utils import PathInfo
|
||||
from django.utils import six
|
||||
from django.utils.datastructures import ImmutableList, OrderedSet
|
||||
from django.utils.deprecation import (
|
||||
|
@ -670,6 +671,50 @@ class Options(object):
|
|||
# links
|
||||
return self.parents[parent] or parent_link
|
||||
|
||||
def get_path_to_parent(self, parent):
|
||||
"""
|
||||
Return a list of PathInfos containing the path from the current
|
||||
model to the parent model, or an empty list if parent is not a
|
||||
parent of the current model.
|
||||
"""
|
||||
if self.model is parent:
|
||||
return []
|
||||
# Skip the chain of proxy to the concrete proxied model.
|
||||
proxied_model = self.concrete_model
|
||||
path = []
|
||||
opts = self
|
||||
for int_model in self.get_base_chain(parent):
|
||||
if int_model is proxied_model:
|
||||
opts = int_model._meta
|
||||
else:
|
||||
final_field = opts.parents[int_model]
|
||||
targets = (final_field.remote_field.get_related_field(),)
|
||||
opts = int_model._meta
|
||||
path.append(PathInfo(final_field.model._meta, opts, targets, final_field, False, True))
|
||||
return path
|
||||
|
||||
def get_path_from_parent(self, parent):
|
||||
"""
|
||||
Return a list of PathInfos containing the path from the parent
|
||||
model to the current model, or an empty list if parent is not a
|
||||
parent of the current model.
|
||||
"""
|
||||
if self.model is parent:
|
||||
return []
|
||||
model = self.concrete_model
|
||||
# Get a reversed base chain including both the current and parent
|
||||
# models.
|
||||
chain = model._meta.get_base_chain(parent)
|
||||
chain.reverse()
|
||||
chain.append(model)
|
||||
# Construct a list of the PathInfos between models in chain.
|
||||
path = []
|
||||
for i, ancestor in enumerate(chain[:-1]):
|
||||
child = chain[i + 1]
|
||||
link = child._meta.get_ancestor_link(ancestor)
|
||||
path.extend(link.get_reverse_path_info())
|
||||
return path
|
||||
|
||||
def _populate_directed_relation_graph(self):
|
||||
"""
|
||||
This method is used by each model to find its reverse objects. As this
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue