ddd
ddd

Reputation: 219

Django REST-framework: Making a field optional

My users can create one or more lists with items.

I'm using django REST-framework and subclass the 'viewsets.ModelViewSet' to receive a json object list_item which has as a foreign key: the list field.

Here is what I want to do:

Testcode (simplified):

test_posting_item_creates_list(self):
    item = {
        'name': "test",
     #   'list': 1,
        'user': self.user.id,

    }
    response = self.client.post('/api/listitems/',
                        json.dumps(item),
                        content_type="application/json")
    self.assertEqual(response.status_code, 201, 'statuscode is 201 created')

This is my serializer

class ItemSerializer(serializers.ModelSerializer):

    # this works for changing the list but a list field is required when posting
    def validate(self, attrs):     
        if 'list' in attrs:
             attrs['list'] = TodayList.objects.create()


    class Meta:
        model = TodayListItem
        fields =('id',
                 'name',
                 'user',
                 'list',
    )

With my validate method I can change the list, to a different one so I tried: if 'list' not in attrs: but that doesnt work.

Is the Serializer the right place to "intercept" the post and create the list? How can I make a field optional?

Upvotes: 1

Views: 7202

Answers (2)

priyankvex
priyankvex

Reputation: 6040

In your serializer you can mark your fields as not required by passing required arguments as False

class UserResponse(ModelSerializer):
    response = IntegerField()
    meta_data = MetaDataSerializer(allow_null=True, required=False)

Upvotes: 2

Othman
Othman

Reputation: 3018

Based on Django REST framework manual

Field-level validation

You can specify custom field-level validation by adding .validate_ methods to your Serializer subclass. These are analogous to .clean_ methods on Django forms, but accept slightly different arguments.

They take a dictionary of deserialized attributes as a first argument, and the field name in that dictionary as a second argument (which will be either the name of the field or the value of the source argument to the field, if one was provided).

So, the Solution is to create a list validation method like this:

def validate_list(self, attrs, source):
    """
    Check that the list is correct or not?
    """
    if list not in attrs:
        list_item = TodayList.objects.create()
        list = list_item.id
    return attrs

Another solution is in the model level, by overriding the save() and check the list id.

def save(self, *args, **kwargs):
    if self.list is None:
        self.list = TodayList.objects.create()
    super(TodayListItem, self).save(*args, **kwargs) # Call the "real" save() method.

Upvotes: 0

Related Questions