Skip to content
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

BooleanField required argument is ignored #1004

Closed
willkg opened this issue Jul 25, 2013 · 13 comments
Closed

BooleanField required argument is ignored #1004

willkg opened this issue Jul 25, 2013 · 13 comments
Labels

Comments

@willkg
Copy link
Contributor

willkg commented Jul 25, 2013

It looks like BooleanFields get a default of False and because of that they can't be required. So doing this has no effect:

foo = serializers.BooleanField(required=True)

I'm pretty sure the problem is this in rest_framework/fields.py BooleanField definition:

    # Note: we set default to `False` in order to fill in missing value not
    # supplied by html form.  TODO: Fix so that only html form input gets
    # this behavior.
    default = False
@tomchristie
Copy link
Member

Seems valid. First obvious step would be for someone to write a failing test case for this and submit it as a pull request.

@willkg
Copy link
Contributor Author

willkg commented Aug 16, 2013

Failing test in a pull request: #1044

yprez added a commit to yprez/django-rest-framework that referenced this issue Aug 19, 2013
Note: The browsable API works fine, without the default being set.
@tomchristie
Copy link
Member

Fixed by 28ff6fb.

@QinMing
Copy link

QinMing commented Sep 16, 2016

I think this issue still exist. Here's my code. I'm using djangorestframework==3.4.6

in models.py

x = models.BooleanField()

in serializers.py

x = serializers.BooleanField(required=True)

POST body (JSON)

{
"y": "no x here"
}

Then I got 500 error:

IntegrityError: (1048, "Column 'x' cannot be null")

What I expect

should return an 400 error saying "x is required".

==== Update ====
Alright I found the reason. The field name I used was "update", which conflicts with the method update on the serializer. I solved the issue by renaming it to something like "is_update".

Sorry @xordoquy for bothering you :P

@xordoquy
Copy link
Collaborator

This is covered by a test so it'll likely be something on your side. A test case highlighting the issue will be required to go further.

@thakryptex
Copy link

I have this problem too. (DRF 3.7.3)
I use simple Serializer (not ModelSerializer), it takes only one parameter 'is_male', which is BooleanField(required=True).
I found that if I didn't pass any parameters to serializer, it passes validation (instead of raising exception) and returns 'is_male' = False.
Something implicit going on there, it shouldn't be this way.

@xordoquy
Copy link
Collaborator

xordoquy commented Dec 4, 2017

As said in previous comment, it's already covered and working with a test case in DRF test suite. So either your code is doing something wrong either there's an issue in DRF. In the later case we'll need a test case we can reproduce to highlight the issue.

@thakryptex
Copy link

Do you need code example to reproduce it?

Ok. I'm writing a test for a view, that have to throw validation error (because 'is_male' argument is required).
response = self.client.post(self.url(self.user.uid), {})
as you can see, post data is empty.

In the view I do this:

request_serializer = ChangeUserGenderSerializer(data=request.POST)
request_serializer.is_valid(raise_exception=True)

so, request.POST is empty (I've this with debugger) and is_valid() have to throw an exception if something goes wrong.

My serializer is:

class ChangeUserGenderSerializer(serializers.Serializer):
    is_male = serializers.BooleanField(required=True)

Result you can see here:
2017-12-04 12 11 02
Somehow it validates and returns False.

If I made a mistake somewhere, please, tell me, but as I can see there is no mistakes in code.

@carltongibson
Copy link
Collaborator

carltongibson commented Dec 4, 2017

OK, but I just tried this in the shell and I get the expected result:

>>> from rest_framework import serializers
>>> class ChangeUserGenderSerializer(serializers.Serializer):
...         is_male = serializers.BooleanField(required=True)
...
>>> serializer = ChangeUserGenderSerializer(data={})
>>> serializer.is_valid()
False
>>> serializer.errors
ReturnDict([('is_male', [u'This field is required.'])])

So there must be something else going on.

@thakryptex Can you add a test case to the test suite that recreates your issue? If we have a failing PR we can see exactly what's going on, and fix it.

@xordoquy
Copy link
Collaborator

xordoquy commented Dec 4, 2017

My bet, it's because data are sent through forms and the outcome would be the one expected.
Which is also why I ask for a test case and not code sample. This helps understand the issue and where is may lay.

@thakryptex
Copy link

Wow. Actually, it's pretty confusing.
Look, if I pass request.POST (or request.data) I get is_valid = True.
But if I pass dict(request.POST), then is_valid = False.

2017-12-04 12 57 23

@xordoquy
Copy link
Collaborator

xordoquy commented Dec 4, 2017

@thakryptex yes it is because it's forms and it's a usage question.
TL:DR you're using forms and all that behavior is expected. There's more about it in the Django documentation for BooleanField.
Now let's not turn this issue into a debug session please.

@thakryptex
Copy link

thakryptex commented Dec 4, 2017

Ok, let's read: Forms BooleanField
What we see there:

Empty value: False
Validates that the value is True (e.g. the check box is checked) if the field has required=True.

So, everything is fine and looks like it supposed to be. (I also checked BooleanField in Models)
But there is no answer on described problem.
Why with request.POST it always valid, but only as dict (request.POST.dict()) it works properly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants