django-rest-framework clarification on field "required" option - python

I have the following serializer:
class ReqSerializer(serializers.ModelSerializer):
class Meta:
model = Earth
fields = ('area', )
and this model:
class Earth(models.Model):
area = models.IntegerField(default=0)
According to django-rest-framework Serializer fields the "required" option is
set to True by default which means if I try to validate the serializer without "area" field in the input,
I should get This field is required error. But is_valid() is passed and the model gets created with default area=0. However, Using this:
extra_kwargs = {
area': {'required': True},
}
Would solve the issue but why? What could change this behavior? Why the default "required=True"
has no effect?
Update:
I just noticed that if I remove the default=0 from the model, it will work as expected. Now the question is why setting default on model field cancels the required=True on serializer.

I believe your problem here is that the field is being automatically generated by Django REST framework, while the docs are coming from the perspective of you manually creating the field on the serializer.
According to django-rest-framework Serializer fields the "required" option is set to True by default
This is correct for fields that you specify on your own on the serializer. In the case of automatically generated fields, Django REST framework tries to determine the serializer field options that best match the model field, similar to how the Django forms does it for form fields. For serializer fields, this is largely undocumented at the moment so there is nothing that I can point you to.
But is_valid() is passed and the model gets created with default area=0. 
This is because Django REST framework determines that the field has a default value, at which point is knows input is not strictly required because the model field will automatically give a default value in the event that the user passes nothing in. Of course, if you pass something into the serializer on creation, the value will be used instead of the default, which is what you would expect if you were manually creating the model.
Would solve the issue but why? What could change this behavior? Why the default "required=True" has no effect?
This will fix your issue because it is manually overriding the required=False that is set on the automatically generated serializer field. In Django REST framework 3.0, you can confirm that by calling repr(ReqSerializer()) and looking at the the automatically generated field.
I just noticed that if I remove the default=0 from the model, it will work as expected.
This is because Django REST framework no longer determines the default and adds the required=True to the serializer, like you were expecting.

Related

Django - attributes and redefined fields with a ModelForm?

I have been learning about how forms, and now ModelForms, work.
In a video by Max Goodridge, he redefines a field for one of his ModelFields in his ModelForm class. That is, he manually adds a field to his ModelForm class that could have been auto-generated by the ModelForm framework. From what I have read and understood thus far, that may be something to avoid. Though, that is not where my question lies.
I am wondering how redefining fields within a ModelForm class works. In the Django Docs, it is stated (with an example) that a ModelForm instance will have a form field for every model field specified. What happens then, when a form field is explicitly defined in a ModelForm instance? Are two fields generated or does ModelForm recognise that a field is already defined, thus not generating another one?
Furthermore, what exactly does adding an attribute to a ModelForm instance in the views do? For example, I have seen this:
form = ExampleForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user # herein lies my confusion
post.save()
What exactly is happening here? I have seen people do this and adding a timestamp as well, but I fail to understand exactly what it does. Presumably, the .save() method recognizes the attribute name 'user' and adds it to the database if the name corresponds with a Model-field name 'user'?
What happens when a form field is explicitly defined in a ModelForm instance?
How does adding an attribute with information for a model-field in a ModelForm instance work?
Thank you!
When you define a field at class level, the form will use that definition rather than create one from the model field. Far from being something to avoid, this is the correct thing to do if you want to completely customise a field.
Your second question is hard to understand. Save is not "recognising" anything. form.save() returns the instance of the model, on which you can set any field values as normal.

Include auto generated primary key in Django ModelForm fields

I have a model where I didn't specify a primary key and Django generated one for me. Now I create a ModelForm for the model and I have specified id in the fields section of ModelForm. However, in my ModelForm object, the id field is not present.
Are only the model fields explicitly declared visible in the ModelForm?
Are only the model fields explicitly declared visible in the
ModelForm?
Yes, generally you don't want to mess with this field, if the user inputs a value for the id field it's very likely to be duplicated so this is something you want django to take care of for you.

Django REST: getting serializer model field's default value

Using Django and REST for my project. At some point I need to access serializer model's field default value (since REST doesn't set default values). The code looks like this:
# try to get default from model, if it is not set then try to get default from serializer
default = serializer.Meta.model._meta.get_field(input_instance.field_name).default
I think this is ugly.
Is there any way to shorten this expression?

Difference between model fields(in django) and serializer fields(in django rest framework)

As we can validate the values using the conventional model field then why Django REST Framework contains its own serializer fields. I know that serializer fields are used to handle the converting between primitive values and internal datatypes. Except this, is there anything different between them.
Well there is a ModelSerializer that can automatically provide the serializer fields based on your model fields (given the duality you described). A ModelSerializer allows you to select which models fields are going to appear as fields in the serializer, thus allowing you to show/hide some fields.
A field in a model, is conventionally tied to a data store (say a column in a database).
A DRF Serializer can exist without a Django model too, as it serves to communicate between the API and the client, and its fields can be in many forms that are independent from the model and the backing database, e.g. ReadOnlyField, SerializerMethodField etc
Model fields are what you keep in your database.
(it answers how you want your data organized)
Serializer fields are what you expose to your clients.
(it answers how you want your data represented)
For models.ForeignKey(User) of your model,
you can represent it in your serializer as an Int field, or UserSerializer(which you will define), or as http link that points to the api endpoint for the user.
You can represent the user with username, it's up to how you want to represent it.
With DRF,
You can hide model fields, mark it as read-only/write-only.
You can also add a field that is not mappable to a model field.
Both of them refers to the same thing with a little bit difference.
Model fields are used within the database i.e while creating the schema, visible to the developer only.
while Serializer fields are used to when exposing the api to the client, visible to client also.

How can I reuse django form for searching?

I am programming an application in django, and I have a model where I defined some fields that are necessary to be filled. This way, when te user doesn't fill one of these fields, Django authomatically indicates to the user to fill it to create the specific object defined by the model.
But myquestion comes here: I want to reuse the same form to search objects defined by that model. And in this case, all the fields that before were necessary, now are OPTIONAL. But, as I have already defined the model so that the fields are necessary, django doesn´t let me define those fields as optional.
Is there any way to reuse that form where the fields are necessary, but making them OPTIONAL? Or I must create another different model or form in html? I know that creating another form manually in the html code the problem is solver, but I have curiosity to know if it can be reused.
Thank you so much!
You can programmatically change properties of a field within a form using its fields dictionary. So you could create a new form class that is derived from your current form class and in its __init__ set the required property of the fields you desired to be optional to be False like so:
self.fields['title'].required = False

Categories