mirror of https://github.com/django/django.git
Fixed #23862 -- Made ManyToManyRel.get_related_field() respect to_field.
This commit is contained in:
parent
a7c3d0f288
commit
c7087bc777
|
@ -1348,11 +1348,18 @@ class ManyToManyRel(object):
|
||||||
|
|
||||||
def get_related_field(self):
|
def get_related_field(self):
|
||||||
"""
|
"""
|
||||||
Returns the field in the to' object to which this relationship is tied
|
Returns the field in the 'to' object to which this relationship is tied.
|
||||||
(this is always the primary key on the target model). Provided for
|
Provided for symmetry with ManyToOneRel.
|
||||||
symmetry with ManyToOneRel.
|
|
||||||
"""
|
"""
|
||||||
return self.to._meta.pk
|
opts = self.through._meta
|
||||||
|
if self.through_fields:
|
||||||
|
field = opts.get_field(self.through_fields[0])
|
||||||
|
else:
|
||||||
|
for field in opts.fields:
|
||||||
|
rel = getattr(field, 'rel', None)
|
||||||
|
if rel and rel.to == self.to:
|
||||||
|
break
|
||||||
|
return field.foreign_related_fields[0]
|
||||||
|
|
||||||
|
|
||||||
class ForeignObject(RelatedField):
|
class ForeignObject(RelatedField):
|
||||||
|
|
|
@ -113,3 +113,25 @@ class Relationship(models.Model):
|
||||||
another = models.ForeignKey(Employee, related_name="rel_another_set", null=True)
|
another = models.ForeignKey(Employee, related_name="rel_another_set", null=True)
|
||||||
target = models.ForeignKey(Employee, related_name="rel_target_set")
|
target = models.ForeignKey(Employee, related_name="rel_target_set")
|
||||||
source = models.ForeignKey(Employee, related_name="rel_source_set")
|
source = models.ForeignKey(Employee, related_name="rel_source_set")
|
||||||
|
|
||||||
|
|
||||||
|
class Ingredient(models.Model):
|
||||||
|
iname = models.CharField(max_length=20, unique=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ('iname',)
|
||||||
|
|
||||||
|
|
||||||
|
class Recipe(models.Model):
|
||||||
|
rname = models.CharField(max_length=20, unique=True)
|
||||||
|
ingredients = models.ManyToManyField(
|
||||||
|
Ingredient, through='RecipeIngredient', related_name='recipes',
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ('rname',)
|
||||||
|
|
||||||
|
|
||||||
|
class RecipeIngredient(models.Model):
|
||||||
|
ingredient = models.ForeignKey(Ingredient, to_field='iname')
|
||||||
|
recipe = models.ForeignKey(Recipe, to_field='rname')
|
||||||
|
|
|
@ -6,7 +6,8 @@ from operator import attrgetter
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from .models import (Person, Group, Membership, CustomMembership,
|
from .models import (Person, Group, Membership, CustomMembership,
|
||||||
PersonSelfRefM2M, Friendship, Event, Invitation, Employee, Relationship)
|
PersonSelfRefM2M, Friendship, Event, Invitation, Employee, Relationship,
|
||||||
|
Ingredient, Recipe, RecipeIngredient)
|
||||||
|
|
||||||
|
|
||||||
class M2mThroughTests(TestCase):
|
class M2mThroughTests(TestCase):
|
||||||
|
@ -426,3 +427,30 @@ class M2mThroughReferentialTests(TestCase):
|
||||||
['peter', 'mary', 'harry'],
|
['peter', 'mary', 'harry'],
|
||||||
attrgetter('name')
|
attrgetter('name')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class M2mThroughToFieldsTests(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.pea = Ingredient.objects.create(iname='pea')
|
||||||
|
self.potato = Ingredient.objects.create(iname='potato')
|
||||||
|
self.tomato = Ingredient.objects.create(iname='tomato')
|
||||||
|
self.curry = Recipe.objects.create(rname='curry')
|
||||||
|
RecipeIngredient.objects.create(recipe=self.curry, ingredient=self.potato)
|
||||||
|
RecipeIngredient.objects.create(recipe=self.curry, ingredient=self.pea)
|
||||||
|
RecipeIngredient.objects.create(recipe=self.curry, ingredient=self.tomato)
|
||||||
|
|
||||||
|
def test_retrieval(self):
|
||||||
|
# Forward retrieval
|
||||||
|
self.assertQuerysetEqual(
|
||||||
|
self.curry.ingredients.all(),
|
||||||
|
[self.pea, self.potato, self.tomato], lambda x: x
|
||||||
|
)
|
||||||
|
# Backward retrieval
|
||||||
|
self.assertEqual(self.tomato.recipes.get(), self.curry)
|
||||||
|
|
||||||
|
def test_choices(self):
|
||||||
|
field = Recipe._meta.get_field('ingredients')
|
||||||
|
self.assertEqual(
|
||||||
|
[choice[0] for choice in field.get_choices(include_blank=False)],
|
||||||
|
['pea', 'potato', 'tomato']
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue