-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue with upgrade from 3.14 to 3.15.1, null values no longer allowed in POST #9410
Comments
Can you pinpoint which commit causes this? (e.g. via |
Tracked it down after a few hours of installing and uninstalling various commits. To confirm, I started up my backend database locally and tested; sure enough, commit b7523 resulted in
It seems this pull request did something: |
We're also experiencing this with paperless-ngx. The API now returns Roughly with these fields and constraints: owner = models.ForeignKey(
User,
blank=True,
null=True,
on_delete=models.SET_NULL,
verbose_name=_("owner"),
)
name = models.CharField(_("name"), max_length=128)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["name", "owner"],
name="%(app_label)s_%(class)s_unique_name_owner",
),
models.UniqueConstraint(
name="%(app_label)s_%(class)s_name_uniq",
fields=["name"],
condition=models.Q(owner__isnull=True),
),
] which I think are pretty un-complicated constraints. |
@peterthomassen |
I'm hoping this is considered an issue that needs to be fixed, not just because changing the front end is a PITA, but mainly because I don't think an API should require users to know and define literally every possible key-value pair when hitting an endpoint. |
@Zolton ex : -
Also please go through my comment in #9378. I have tried to reproduce the error. I used foreign key like it was done by you but I'm able to send a POST request without a parameter which is also a foreign key. I didn't receive any error. |
While its true that the solution above def create(self, validated_data):
if "owner" not in validated_data and self.user:
validated_data["owner"] = self.user The above snippet allowed us to distinguish between the situation where the Edit: I can workaround this with e.g. |
I understand. But none of the contributors have confirmed if this will be considered an issue and will be worked upon. Waiting if someone responds. |
oh yes, I completely agree. Hope I didn’t sound argumentative or anything like that, just adding some input. Also I really appreciate you pointing out the workaround, it’s at least a path forward for us for now! Thank you. |
Thanks so much for trying it! I went through my code and compared it to the PR that started this (#7438), which mostly centered around a change in the get_unique_together serializer. Update: overriding perform_create and using get_or_create has no effect; I get the same error when I don't override and just rely on the default/built-in create functions |
I think it was done in a major version from 3.14 to 3.15 and the reason was valid behind the change. but I am willing to know counter logic /fixes |
To follow up on this, setting default=None fixed the issue; but this is fairly unexpected since I had blank=True and null=True as well, which has been working for quite awhile now. I think the reason your code isn't able to reproduce the issue is it doesn't have any constraints. In my original post, if I remove the class Meta: constraints array, then missing key-value pairs are accepted just fine in my tests, so the real issue seems to be that applying constraints causes those fields to become required, and omissions aren't treated as null. To the issue of the bug, I found this tidbit under https://www.django-rest-framework.org/api-guide/validators/,
So the UniqueTogetherValidator makes things required, but the docs also say this:
And then there's this:
So:
It seems there's a tension between these statements, and I'm guessing a kind of hierarchy between which one wins existed before, but was changed by the PR I mentioned above I'm not particularly well-versed in Django code and could easily be wrong, but my best guess is that this is why null=True was fine before - default was being set automatically and was higher in the hierarchy, and with the PR change, it's now lower in the undocumented hierarchy |
UniqueConstraint can be conditional with check if field is not null (this case is not fully supported with recent changes). In case when model have a field with null=True and blank=True, serializer should not change this field to required. Also some fields can be set automatically in pre_save signal of model for example, but with new changes serializer validation will fail first... this changes definitely should be in major release as lot's of code could be broken during upgrade from 3.14 to 3.15 |
Is a new version expected with this fix and others related toUniqueConstraint ? The support for UniqueConstraint is not complete and may cause issues… |
Checklist
3.15.1 is causing problems in prod with a change to how null values are handled.
Currently running Django. 5.0.6, django-cors-headers 4.3.1, and gunicorn 22.0.0
As an example, I have a table that keeps track of a person, an organization, and some small tidbit of info about them, with the constraint that at least 2 fields must always be filled out and have unique information:
The idea is, of the 3 fields, at least 2 must be filled out. So in 3.14, I could send a POST request like
or
And just leave out one of the fields out, it'd just be null in the database - which is exactly what we want; if there's no info, just leave it null
Now in 3.15.1, this results in a 400 Bad Request, and the error message,
"This field is required".
This is causing problems because now all our front end requests have to be rewritten as
In the above case, Information would still reflected in the database as Null in the database.
Our issue is having to include a blank string in POST requests, when previously, just omitting the key-value pair was enough to cause a null value. We'd prefer not having to change every single POST format, and keep the old habit of "If a key-value is not present, it's just null", instead of having to write in an empty string
The text was updated successfully, but these errors were encountered: