Browse Source

Fixed #33084 -- Removed incorrect system check for ManyToManyField with limit_choices_to.

Hasan Ramezani 3 years ago
parent
commit
0a28b42b15

+ 0 - 11
django/db/models/fields/related.py

@@ -1247,17 +1247,6 @@ class ManyToManyField(RelatedField):
                     id='fields.W341',
                 )
             )
-        if (self.remote_field.limit_choices_to and self.remote_field.through and
-                not self.remote_field.through._meta.auto_created):
-            warnings.append(
-                checks.Warning(
-                    'limit_choices_to has no effect on ManyToManyField '
-                    'with a through model.',
-                    obj=self,
-                    id='fields.W343',
-                )
-            )
-
         if self.remote_field.symmetrical and self._related_name:
             warnings.append(
                 checks.Warning(

+ 1 - 1
docs/ref/checks.txt

@@ -310,7 +310,7 @@ Related fields
 * **fields.W342**: Setting ``unique=True`` on a ``ForeignKey`` has the same
   effect as using a ``OneToOneField``.
 * **fields.W343**: ``limit_choices_to`` has no effect on ``ManyToManyField``
-  with a ``through`` model.
+  with a ``through`` model. *This check appeared before Django 4.0.*
 * **fields.W344**: The field's intermediary table ``<table name>`` clashes with
   the table name of ``<model>``/``<model>.<field name>``.
 * **fields.W345**: ``related_name`` has no effect on ``ManyToManyField`` with a

+ 0 - 4
docs/ref/models/fields.txt

@@ -1810,10 +1810,6 @@ that control how the relationship functions.
 
     Same as :attr:`ForeignKey.limit_choices_to`.
 
-    ``limit_choices_to`` has no effect when used on a ``ManyToManyField`` with a
-    custom intermediate table specified using the
-    :attr:`~ManyToManyField.through` parameter.
-
 .. attribute:: ManyToManyField.symmetrical
 
     Only used in the definition of ManyToManyFields on self. Consider the

+ 1 - 27
tests/invalid_models_tests/test_relative_fields.py

@@ -81,32 +81,12 @@ class RelativeFieldTests(SimpleTestCase):
         field = Model._meta.get_field('m2m')
         self.assertEqual(field.check(from_model=Model), [])
 
-    def test_many_to_many_with_limit_choices_auto_created_no_warning(self):
-        class Model(models.Model):
-            name = models.CharField(max_length=20)
-
-        class ModelM2M(models.Model):
-            m2m = models.ManyToManyField(Model, limit_choices_to={'name': 'test_name'})
-
-        self.assertEqual(ModelM2M.check(), [])
-
     def test_many_to_many_with_useless_options(self):
         class Model(models.Model):
             name = models.CharField(max_length=20)
 
         class ModelM2M(models.Model):
-            m2m = models.ManyToManyField(
-                Model,
-                null=True,
-                validators=[lambda x: x],
-                limit_choices_to={'name': 'test_name'},
-                through='ThroughModel',
-                through_fields=('modelm2m', 'model'),
-            )
-
-        class ThroughModel(models.Model):
-            model = models.ForeignKey('Model', models.CASCADE)
-            modelm2m = models.ForeignKey('ModelM2M', models.CASCADE)
+            m2m = models.ManyToManyField(Model, null=True, validators=[lambda x: x])
 
         field = ModelM2M._meta.get_field('m2m')
         self.assertEqual(ModelM2M.check(), [
@@ -120,12 +100,6 @@ class RelativeFieldTests(SimpleTestCase):
                 obj=field,
                 id='fields.W341',
             ),
-            DjangoWarning(
-                'limit_choices_to has no effect on ManyToManyField '
-                'with a through model.',
-                obj=field,
-                id='fields.W343',
-            ),
         ])
 
     def test_many_to_many_with_useless_related_name(self):

+ 17 - 0
tests/model_forms/models.py

@@ -480,3 +480,20 @@ class NullableUniqueCharFieldModel(models.Model):
     email = models.EmailField(blank=True, null=True)
     slug = models.SlugField(blank=True, null=True)
     url = models.URLField(blank=True, null=True)
+
+
+class Number(models.Model):
+    value = models.IntegerField()
+
+
+class NumbersToDice(models.Model):
+    number = models.ForeignKey('Number', on_delete=models.CASCADE)
+    die = models.ForeignKey('Dice', on_delete=models.CASCADE)
+
+
+class Dice(models.Model):
+    numbers = models.ManyToManyField(
+        Number,
+        through=NumbersToDice,
+        limit_choices_to=models.Q(value__gte=1),
+    )

+ 15 - 2
tests/model_forms/tests.py

@@ -21,10 +21,10 @@ from django.test.utils import isolate_apps
 from .models import (
     Article, ArticleStatus, Author, Author1, Award, BetterWriter, BigInt, Book,
     Category, Character, Colour, ColourfulItem, CustomErrorMessage, CustomFF,
-    CustomFieldForExclusionModel, DateTimePost, DerivedBook, DerivedPost,
+    CustomFieldForExclusionModel, DateTimePost, DerivedBook, DerivedPost, Dice,
     Document, ExplicitPK, FilePathModel, FlexibleDatePost, Homepage,
     ImprovedArticle, ImprovedArticleWithParentLink, Inventory,
-    NullableUniqueCharFieldModel, Person, Photo, Post, Price, Product,
+    NullableUniqueCharFieldModel, Number, Person, Photo, Post, Price, Product,
     Publication, PublicationDefaults, StrictAssignmentAll,
     StrictAssignmentFieldSpecific, Student, StumpJoke, TextFile, Triple,
     Writer, WriterProfile, test_images,
@@ -2896,6 +2896,19 @@ class LimitChoicesToTests(TestCase):
             [self.marley, self.threepwood],
         )
 
+    def test_limit_choices_to_m2m_through(self):
+        class DiceForm(forms.ModelForm):
+            class Meta:
+                model = Dice
+                fields = ['numbers']
+
+        Number.objects.create(value=0)
+        n1 = Number.objects.create(value=1)
+        n2 = Number.objects.create(value=2)
+
+        form = DiceForm()
+        self.assertCountEqual(form.fields['numbers'].queryset, [n1, n2])
+
 
 class FormFieldCallbackTests(SimpleTestCase):