Kaydet (Commit) c7087bc7 authored tarafından Simon Charette's avatar Simon Charette Kaydeden (comit) Tim Graham

Fixed #23862 -- Made ManyToManyRel.get_related_field() respect to_field.

üst a7c3d0f2
......@@ -1348,11 +1348,18 @@ class ManyToManyRel(object):
def get_related_field(self):
"""
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
symmetry with ManyToOneRel.
Returns the field in the 'to' object to which this relationship is tied.
Provided for 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):
......
......@@ -113,3 +113,25 @@ class Relationship(models.Model):
another = models.ForeignKey(Employee, related_name="rel_another_set", null=True)
target = models.ForeignKey(Employee, related_name="rel_target_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 .models import (Person, Group, Membership, CustomMembership,
PersonSelfRefM2M, Friendship, Event, Invitation, Employee, Relationship)
PersonSelfRefM2M, Friendship, Event, Invitation, Employee, Relationship,
Ingredient, Recipe, RecipeIngredient)
class M2mThroughTests(TestCase):
......@@ -426,3 +427,30 @@ class M2mThroughReferentialTests(TestCase):
['peter', 'mary', 'harry'],
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']
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment