But today i noticed our database removes all foreignkeys and adds them
again. After some debugging i found the issue in this condition:
https://github.com/django/django/blob/master/django/db/models/fields/related_descriptors.py#L1004
Our form returns all Foreignkeys as list of strings in cleaned_data, but
the strings do not match the pk (int). After converting the strings to
int, before calling set(), fixes the problem.
Question:
How to avoid this issue? Maybe all code usages of set() are using lists of
strings, maybe not. I dont know at the moment.
Is is possible Django fixes this issue? Should Django fix the issue? Maybe
strings should raise an exception?
--
Ticket URL: <https://code.djangoproject.com/ticket/31095>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:1>
* version: 1.11 => master
* type: Bug => Cleanup/optimization
* easy: 0 => 1
* stage: Unreviewed => Accepted
Comment:
We cannot raise an exception on strings because `set()` accepts the field
the relation points, e.g. `CharField`. However we can optimize this with
preparing values, i.e.
{{{
diff --git a/django/db/models/fields/related_descriptors.py
b/django/db/models/fields/related_descriptors.py
index a9445d5d10..9f82ca4e8c 100644
--- a/django/db/models/fields/related_descriptors.py
+++ b/django/db/models/fields/related_descriptors.py
@@ -999,7 +999,7 @@ def create_forward_many_to_many_manager(superclass,
rel, reverse):
for obj in objs:
fk_val = (
self.target_field.get_foreign_related_value(obj)[0]
- if isinstance(obj, self.model) else obj
+ if isinstance(obj, self.model) else
self.target_field.get_prep_value(obj)
)
if fk_val in old_ids:
old_ids.remove(fk_val)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:2>
* owner: nobody => Hasan Ramezani
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:3>
* has_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:4>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"a3fc24f01484d4bdd106bc6d7c49049fc5352af6" a3fc24f0]:
{{{
#!CommitTicketReference repository=""
revision="a3fc24f01484d4bdd106bc6d7c49049fc5352af6"
Fixed #31095 -- Made RelatedManager.set() preserve existing m2m relations
with an invalid type.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:5>
Comment (by TZanke):
Thank you! Will this be back ported to any other Django version?
The following line looks very similar, should this also be fixed?
https://github.com/django/django/blob/master/django/db/models/fields/related_descriptors.py#L743
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:6>
Comment (by felixxm):
> Thank you! Will this be back ported to any other Django version?
No, this patch doesn't qualify for a backport, it will be included in
Django 3.1.
> The following line looks very similar, should this also be fixed?
No, in this case `set()` expects models instances, so it's not affected.
--
Ticket URL: <https://code.djangoproject.com/ticket/31095#comment:7>