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
Alter read_only+default behaviour #5886
Alter read_only+default behaviour #5886
Conversation
@encode/django-rest-framework-core-team Can I ask for input on this please? Breaking BC for a long-standing behaviour isn't top of my list of things to do. Thanks. |
|
Hi @ticosax. #5708 is on my radar here. There's a little bit of unpicking to do to get to it directly though. (There are a few related points.) Following this I'm expecting now that we will revert #5639. I'm then hoping that we've pinned down the whole nest of issues here. To wit: any test cases you think are missing, anywhere in this ballpark would be very welcome. |
I think I made a mistake in my previous comment. there is no relation between the fixed behavior in our test suite and this PR. sorry. I will try to isolate better the changes. |
Yup looks good to me, and I think it's more intuitive behaviour this way around. |
In this context (without mentioning `save`) now slightly misleading.
With this change, what is the correct way to do unique-together validation where one of the fields is a read-only field? In my case, owner = serializers.PrimaryKeyRelatedField(
read_only=True,
default=serializers.CreateOnlyDefault(serializers.CurrentUserDefault()),
) but that field is now ignored. When |
Hi @akx. Can you put that into a minimal test-case please? The Relevant test case is in
It has a case for read-only fields: django-rest-framework/tests/test_validators.py Lines 260 to 278 in bc35345
So we may need to make an adjustment. |
@carltongibson Sure thing. Here you are: https://github.com/akx/drf_unique_together_testcase I get error 400, as expected, on DRF 3.7.x, and an IntegrityError on DRF 3.8.x. |
@akx Awesome thanks. I'll have a look. |
@carltongibson Should I create an issue for this, erm, issue, for better tracking? |
Would it be worth adding a note to http://www.django-rest-framework.org/api-guide/validators/#advanced-field-defaults where it says
The |
Yeah, maybe. It is mentioned in the unique_together docs, but calling it out further may have value. |
I wonder if overriding |
@blueyed: Yes — that's one way. Either, in the view with the The key is that (because of the whole history here) we need the user to pass the value on save somewhere. The question is how best to add that to the docs. (I don't think it'll need much.) You're the ones reading them: PRs welcome 🙂. |
It was cool that I got to spend a day-and-a-half trying to figure out why I was getting a :-\ |
This was nearly the headline of the 3.8 release notes. |
Hi @mikelane. Contributions and suggestions are always welcome. If you have a minimal example where the behavior is suboptimal and what a helpful exception might have been, it would be appreciated. There's always a chance to improve the error handling and assertion guards. |
This reverts commit c2b24f8.
The docs are misleading on this issue: |
Hi @johnmatthewtennant. Can you be more specific on what's misleading? Also, if you have the time, opening a PR with a documentation update would be helpful. If not, just open a separate issue so we don't lose track of the discrepancy. |
The docs recommend "If you want the date field to be visible, but not editable by the user, then set read_only=True and additionally set a default=... argument." It then says: "The field will not be writable to the user, but the default value will still be passed through to the validated_data." This is not true. It will not be passed through to the validated_data. |
Thanks - I opened a new issue pointing to your comment so this isn't forgotten. |
* Always exclude read_only fields from _writable_fields * Remove `read_only` from `CreateOnlyDefault` example. In this context (without mentioning `save`) now slightly misleading.
Since ≈forever
read_only
fields with adefault
have set that default invalidated_data
on create and update operations.This has led to issues as we have tried to Fix default value handling for dotted sources #5375: uses such as
source=a.b.c, default='x'
where e.g.b
may be null were returningNone
, rather than the defaultx
.#5375 resolved the serialisation issues with dotted
source
—default
will be used if any step in the chain isNone
— but revealed a latent issue for deserialisation when usingread_only
plus adefault
. This comes up in a couple of ways:validated_data
ends up including a nested dict, which cannot be assigned in e.g. places where a model object is expected. not required read_only Fields with allow_null #5708 (comment)Both of these cases come up because the
default
meansread_only
fields end up in_writable_fields
.Whilst we've been doing it ≈forever, it's still a Que? here. How on earth is a
read_only
field writable?This PR adjusts the
_writable_fields
check to always excluderead_only
fields.This is a backwards incompatible change.
The previous use-case was for e.g. setting the current user as the owner of a object on create.
This change will require an extra workaround — to explicitly add the
read_only
fields with a writable default tovalidated_data
, probably by overridingsave
.Possibly we could add some convenience to this? (I'm a bit loathe to add API here.)
Note that in the tutorial we demonstrate this kind of this at the view level:
My overall take here is that the previous use-case saves a line or two, and is a convenience, but it inhibits correctness with the dotted source issue, so I think we need to swallow the pill on this one and make the change.
TODO: