Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nullable ForeignKey fields in Django REST framework

Tags:

In Django REST framework (2.1.16) I have a model with nullable FK field type, but POST creation request gives 400 bad request which says that field is required.

My model is

class Product(Model):
    barcode = models.CharField(max_length=13)
    type = models.ForeignKey(ProdType, null=True, blank=True)

and serializer is:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        exclude = ('id')

I've tried to add type explicitly to serializer like

class ProductSerializer(serializers.ModelSerializer):
    type = serializers.PrimaryKeyRelatedField(null=True, source='type')
    class Meta:
        model = Product
        exclude = ('id')

and it has no effect.

From http://django-rest-framework.org/topics/release-notes.html#21x-series I see that there was a bug, but it was fixed in 2.1.7.

How should I change serializer to properly handle my FK field?

Thanks!


UPDATE: from the shell it gives

>>> serializer = ProductSerializer(data={'barcode': 'foo', 'type': None})
>>> print serializer.is_valid()
True
>>> 
>>> print serializer.errors
{}

but without type=None:

>>> serializer = ProductSerializer(data={'barcode': 'foo'})
>>> print serializer.is_valid()
False
>>> print serializer.errors
{'type': [u'This field is required.']}
>>> serializer.fields['type']
<rest_framework.relations.PrimaryKeyRelatedField object at 0x22a6cd0>
>>> print serializer.errors
{'type': [u'This field is required.']}

in both cases it gives

>>> serializer.fields['type'].null
True
>>> serializer.fields['type'].__dict__
{'read_only': False, ..., 'parent': <prodcomp.serializers.ProductSerializer object at   0x22a68d0>, ...'_queryset': <mptt.managers.TreeManager object at 0x21bd1d0>, 'required': True, 
like image 892
Dmitry Ziolkovskiy Avatar asked Jan 17 '13 15:01

Dmitry Ziolkovskiy


People also ask

Can ForeignKey be null in Django?

django rest framework - ForeignKey does not allow null values - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.

What is to_ representation Django?

to_representation(self, value) method. This method takes the target of the field as the value argument, and should return the representation that should be used to serialize the target. The value argument will typically be a model instance.

What is serializer method field in Django?

Each field in a Form class is responsible not only for validating data, but also for "cleaning" it — normalizing it to a consistent format. — Django documentation. Serializer fields handle converting between primitive values and internal datatypes.


2 Answers

Add the kwarg allow_null when initializing the serializer:

class ProductSerializer(serializers.ModelSerializer):
    type = serializers.PrimaryKeyRelatedField(null=True, source='type', allow_null=True)

As already mentioned in the comment of @gabn88 but I think it warrants its own answer. (Cost me some time because I only read that comment after finding it out by myself.)

See http://www.django-rest-framework.org/api-guide/relations/

like image 166
Risadinha Avatar answered Sep 28 '22 05:09

Risadinha


I'm not sure what's going on there, we've got coverage for that case and similar cases work fine for me.

Perhaps try dropping into the shell and inspecting the serializer directly.

For example if you instantiate the serializer, what does serializer.fields return? How about serializer.field['type'].null? If you pass data to the serializer directly in the shell what results do you get?

For example:

serializer = ProductSerializer(data={'barcode': 'foo', 'type': None})
print serializer.is_valid()
print serializer.errors

If you get some answers to those, update the question and we'll see if we can get it sorted.

Edit

Okay, that explains things better. The 'type' field is nullable, so it may be None, but it's still a required field. If you want it to be null you have to explicitly set it to None.

If you really do want to be able to exclude the field when POSTing the data, you can include the required=False flag on the serializer field.

like image 27
Tom Christie Avatar answered Sep 28 '22 05:09

Tom Christie