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

This commit is contained in:
Hasan Ramezani 2021-09-08 13:57:49 +02:00 committed by Mariusz Felisiak
parent 46c8df640c
commit 0a28b42b15
6 changed files with 34 additions and 45 deletions

View File

@ -1247,17 +1247,6 @@ class ManyToManyField(RelatedField):
id='fields.W341', 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: if self.remote_field.symmetrical and self._related_name:
warnings.append( warnings.append(
checks.Warning( checks.Warning(

View File

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

View File

@ -1810,10 +1810,6 @@ that control how the relationship functions.
Same as :attr:`ForeignKey.limit_choices_to`. 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 .. attribute:: ManyToManyField.symmetrical
Only used in the definition of ManyToManyFields on self. Consider the Only used in the definition of ManyToManyFields on self. Consider the

View File

@ -81,32 +81,12 @@ class RelativeFieldTests(SimpleTestCase):
field = Model._meta.get_field('m2m') field = Model._meta.get_field('m2m')
self.assertEqual(field.check(from_model=Model), []) 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): def test_many_to_many_with_useless_options(self):
class Model(models.Model): class Model(models.Model):
name = models.CharField(max_length=20) name = models.CharField(max_length=20)
class ModelM2M(models.Model): class ModelM2M(models.Model):
m2m = models.ManyToManyField( m2m = models.ManyToManyField(Model, null=True, validators=[lambda x: x])
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)
field = ModelM2M._meta.get_field('m2m') field = ModelM2M._meta.get_field('m2m')
self.assertEqual(ModelM2M.check(), [ self.assertEqual(ModelM2M.check(), [
@ -120,12 +100,6 @@ class RelativeFieldTests(SimpleTestCase):
obj=field, obj=field,
id='fields.W341', 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): def test_many_to_many_with_useless_related_name(self):

View File

@ -480,3 +480,20 @@ class NullableUniqueCharFieldModel(models.Model):
email = models.EmailField(blank=True, null=True) email = models.EmailField(blank=True, null=True)
slug = models.SlugField(blank=True, null=True) slug = models.SlugField(blank=True, null=True)
url = models.URLField(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),
)

View File

@ -21,10 +21,10 @@ from django.test.utils import isolate_apps
from .models import ( from .models import (
Article, ArticleStatus, Author, Author1, Award, BetterWriter, BigInt, Book, Article, ArticleStatus, Author, Author1, Award, BetterWriter, BigInt, Book,
Category, Character, Colour, ColourfulItem, CustomErrorMessage, CustomFF, Category, Character, Colour, ColourfulItem, CustomErrorMessage, CustomFF,
CustomFieldForExclusionModel, DateTimePost, DerivedBook, DerivedPost, CustomFieldForExclusionModel, DateTimePost, DerivedBook, DerivedPost, Dice,
Document, ExplicitPK, FilePathModel, FlexibleDatePost, Homepage, Document, ExplicitPK, FilePathModel, FlexibleDatePost, Homepage,
ImprovedArticle, ImprovedArticleWithParentLink, Inventory, ImprovedArticle, ImprovedArticleWithParentLink, Inventory,
NullableUniqueCharFieldModel, Person, Photo, Post, Price, Product, NullableUniqueCharFieldModel, Number, Person, Photo, Post, Price, Product,
Publication, PublicationDefaults, StrictAssignmentAll, Publication, PublicationDefaults, StrictAssignmentAll,
StrictAssignmentFieldSpecific, Student, StumpJoke, TextFile, Triple, StrictAssignmentFieldSpecific, Student, StumpJoke, TextFile, Triple,
Writer, WriterProfile, test_images, Writer, WriterProfile, test_images,
@ -2896,6 +2896,19 @@ class LimitChoicesToTests(TestCase):
[self.marley, self.threepwood], [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): class FormFieldCallbackTests(SimpleTestCase):