From 81963b37a92ef583b9f725f1a78dd2ca97c1ab95 Mon Sep 17 00:00:00 2001 From: Andrey Fedoseev Date: Mon, 11 Jul 2016 13:01:43 -0700 Subject: [PATCH] Fixed #17657 -- Made ModelForm respect ModelMultipleChoiceField's to_field_name. Follow up to 67d984413c9540074e4fe6aa033081a35cf192bc. --- django/db/models/fields/related.py | 7 +- tests/model_fields/test_manytomanyfield.py | 4 +- tests/model_forms/tests.py | 91 +++++----------------- 3 files changed, 24 insertions(+), 78 deletions(-) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 8cc174bdfb..e2313e08fd 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -1663,11 +1663,8 @@ class ManyToManyField(RelatedField): Return the value of this field in the given model instance. """ if obj.pk is None: - return [] - qs = getattr(obj, self.attname).all() - if qs._result_cache is not None: - return [item.pk for item in qs] - return list(qs.values_list('pk', flat=True)) + return self.related_model.objects.none() + return getattr(obj, self.attname).all() def save_form_data(self, instance, data): getattr(instance, self.attname).set(data) diff --git a/tests/model_fields/test_manytomanyfield.py b/tests/model_fields/test_manytomanyfield.py index 3134a33197..e4f1c0469d 100644 --- a/tests/model_fields/test_manytomanyfield.py +++ b/tests/model_fields/test_manytomanyfield.py @@ -12,7 +12,9 @@ class ManyToManyFieldTests(SimpleTestCase): m2m = models.ManyToManyField('self', models.CASCADE) instance = ManyToManyModel() - self.assertEqual(instance._meta.get_field('m2m').value_from_object(instance), []) + qs = instance._meta.get_field('m2m').value_from_object(instance) + self.assertEqual(qs.model, ManyToManyModel) + self.assertEqual(list(qs), []) def test_abstract_model_pending_operations(self): """ diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index 40260538c8..9de1a7f24b 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -963,78 +963,6 @@ class UniqueTest(TestCase): self.assertEqual(form.errors['title'], ["Post's Title not unique for Posted date."]) -class ModelToDictTests(TestCase): - """ - Tests for forms.models.model_to_dict - """ - def test_model_to_dict_many_to_many(self): - categories = [ - Category(name='TestName1', slug='TestName1', url='url1'), - Category(name='TestName2', slug='TestName2', url='url2'), - Category(name='TestName3', slug='TestName3', url='url3') - ] - for c in categories: - c.save() - writer = Writer(name='Test writer') - writer.save() - - art = Article( - headline='Test article', - slug='test-article', - pub_date=datetime.date(1988, 1, 4), - writer=writer, - article='Hello.' - ) - art.save() - for c in categories: - art.categories.add(c) - art.save() - - with self.assertNumQueries(1): - d = model_to_dict(art) - - # Ensure all many-to-many categories appear in model_to_dict - for c in categories: - self.assertIn(c.pk, d['categories']) - # Ensure many-to-many relation appears as a list - self.assertIsInstance(d['categories'], list) - - def test_reuse_prefetched(self): - # model_to_dict should not hit the database if it can reuse - # the data populated by prefetch_related. - categories = [ - Category(name='TestName1', slug='TestName1', url='url1'), - Category(name='TestName2', slug='TestName2', url='url2'), - Category(name='TestName3', slug='TestName3', url='url3') - ] - for c in categories: - c.save() - writer = Writer(name='Test writer') - writer.save() - - art = Article( - headline='Test article', - slug='test-article', - pub_date=datetime.date(1988, 1, 4), - writer=writer, - article='Hello.' - ) - art.save() - for c in categories: - art.categories.add(c) - - art = Article.objects.prefetch_related('categories').get(pk=art.pk) - - with self.assertNumQueries(0): - d = model_to_dict(art) - - # Ensure all many-to-many categories appear in model_to_dict - for c in categories: - self.assertIn(c.pk, d['categories']) - # Ensure many-to-many relation appears as a list - self.assertIsInstance(d['categories'], list) - - class ModelFormBasicTests(TestCase): def create_basic_data(self): self.c1 = Category.objects.create( @@ -1788,6 +1716,25 @@ class ModelMultipleChoiceFieldTests(TestCase): sql, params = queryset.query.sql_with_params() self.assertEqual(len(params), 1) + def test_to_field_name_with_initial_data(self): + class ArticleCategoriesForm(forms.ModelForm): + categories = forms.ModelMultipleChoiceField(Category.objects.all(), to_field_name='slug') + + class Meta: + model = Article + fields = ['categories'] + + article = Article.objects.create( + headline='Test article', + slug='test-article', + pub_date=datetime.date(1988, 1, 4), + writer=Writer.objects.create(name='Test writer'), + article='Hello.', + ) + article.categories.add(self.c2, self.c3) + form = ArticleCategoriesForm(instance=article) + self.assertEqual(form['categories'].value(), [self.c2.slug, self.c3.slug]) + class ModelOneToOneFieldTests(TestCase): def test_modelform_onetoonefield(self):