mirror of
https://github.com/django/django.git
synced 2025-10-10 15:29:11 +00:00
Fixed #36481 -- Fixed QuerySet.update concrete fields check.
FieldError is now emitted for invalid update calls involving reverse relations, where previously they failed with AttributeError.
This commit is contained in:
parent
11c2c9ac17
commit
bad03eb108
@ -87,15 +87,12 @@ class UpdateQuery(Query):
|
|||||||
values_seq = []
|
values_seq = []
|
||||||
for name, val in values.items():
|
for name, val in values.items():
|
||||||
field = self.get_meta().get_field(name)
|
field = self.get_meta().get_field(name)
|
||||||
direct = (
|
|
||||||
not (field.auto_created and not field.concrete) or not field.concrete
|
|
||||||
)
|
|
||||||
model = field.model._meta.concrete_model
|
model = field.model._meta.concrete_model
|
||||||
if field.name == "pk" and model._meta.is_composite_pk:
|
if field.name == "pk" and model._meta.is_composite_pk:
|
||||||
raise FieldError(
|
raise FieldError(
|
||||||
"Composite primary key fields must be updated individually."
|
"Composite primary key fields must be updated individually."
|
||||||
)
|
)
|
||||||
if not direct or (field.is_relation and field.many_to_many):
|
if not field.concrete or (field.is_relation and field.many_to_many):
|
||||||
raise FieldError(
|
raise FieldError(
|
||||||
"Cannot update model field %r (only non-relations and "
|
"Cannot update model field %r (only non-relations and "
|
||||||
"foreign keys permitted)." % field
|
"foreign keys permitted)." % field
|
||||||
|
@ -169,13 +169,16 @@ class CompositePKUpdateTests(TestCase):
|
|||||||
token_3 = Token.objects.get(pk=self.token_3.pk)
|
token_3 = Token.objects.get(pk=self.token_3.pk)
|
||||||
self.assertEqual(token_3.secret, "bar")
|
self.assertEqual(token_3.secret, "bar")
|
||||||
|
|
||||||
def test_cant_update_to_unsaved_object(self):
|
def test_cant_update_relation(self):
|
||||||
msg = (
|
msg = (
|
||||||
"Unsaved model instance <User: User object ((None, None))> cannot be used "
|
"Cannot update model field <django.db.models.fields.related.ForeignObject: "
|
||||||
"in an ORM query."
|
"user> (only non-relations and foreign keys permitted)"
|
||||||
)
|
)
|
||||||
|
|
||||||
with self.assertRaisesMessage(ValueError, msg):
|
with self.assertRaisesMessage(FieldError, msg):
|
||||||
|
Comment.objects.update(user=self.user_1)
|
||||||
|
|
||||||
|
with self.assertRaisesMessage(FieldError, msg):
|
||||||
Comment.objects.update(user=User())
|
Comment.objects.update(user=User())
|
||||||
|
|
||||||
def test_cant_update_pk_field(self):
|
def test_cant_update_pk_field(self):
|
||||||
|
@ -41,6 +41,9 @@ class Foo(models.Model):
|
|||||||
|
|
||||||
class Bar(models.Model):
|
class Bar(models.Model):
|
||||||
foo = models.ForeignKey(Foo, models.CASCADE, to_field="target")
|
foo = models.ForeignKey(Foo, models.CASCADE, to_field="target")
|
||||||
|
o2o_foo = models.OneToOneField(
|
||||||
|
Foo, models.CASCADE, related_name="o2o_bar", null=True
|
||||||
|
)
|
||||||
m2m_foo = models.ManyToManyField(Foo, related_name="m2m_foo")
|
m2m_foo = models.ManyToManyField(Foo, related_name="m2m_foo")
|
||||||
x = models.IntegerField(default=0)
|
x = models.IntegerField(default=0)
|
||||||
|
|
||||||
|
@ -173,6 +173,30 @@ class AdvancedTests(TestCase):
|
|||||||
with self.assertRaisesMessage(FieldError, msg):
|
with self.assertRaisesMessage(FieldError, msg):
|
||||||
Foo.objects.update(m2m_foo="whatever")
|
Foo.objects.update(m2m_foo="whatever")
|
||||||
|
|
||||||
|
def test_update_reverse_fk_descriptor(self):
|
||||||
|
msg = (
|
||||||
|
"Cannot update model field <ManyToOneRel: update.bar> "
|
||||||
|
"(only non-relations and foreign keys permitted)."
|
||||||
|
)
|
||||||
|
with self.assertRaisesMessage(FieldError, msg):
|
||||||
|
Foo.objects.update(bar="whatever")
|
||||||
|
|
||||||
|
def test_update_reverse_o2o_descriptor(self):
|
||||||
|
msg = (
|
||||||
|
"Cannot update model field <OneToOneRel: update.bar> "
|
||||||
|
"(only non-relations and foreign keys permitted)."
|
||||||
|
)
|
||||||
|
with self.assertRaisesMessage(FieldError, msg):
|
||||||
|
Foo.objects.update(o2o_bar="whatever")
|
||||||
|
|
||||||
|
def test_update_reverse_mti_parent_link_descriptor(self):
|
||||||
|
msg = (
|
||||||
|
"Cannot update model field <OneToOneRel: update.uniquenumberchild> "
|
||||||
|
"(only non-relations and foreign keys permitted)."
|
||||||
|
)
|
||||||
|
with self.assertRaisesMessage(FieldError, msg):
|
||||||
|
UniqueNumber.objects.update(uniquenumberchild="whatever")
|
||||||
|
|
||||||
def test_update_transformed_field(self):
|
def test_update_transformed_field(self):
|
||||||
A.objects.create(x=5)
|
A.objects.create(x=5)
|
||||||
A.objects.create(x=-6)
|
A.objects.create(x=-6)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user