1

I am working on ModelSerializers in Django rest-framework.

models.py

from __future__ import unicode_literals
from django.db import models
from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.fields import HStoreField
from django.contrib.postgres.validators import KeysValidator

    class Component(models.Model):
        component_name = models.CharField(max_length=50)
        allowed_extensions = ArrayField(models.CharField(max_length=50))

        def __str__(self):
            return self.component_name

    class Image_Type(models.Model):
        image_name = models.CharField(max_length=30)
        def __str__(self):
            return self.image_name
    class Image_Component(models.Model):
        component_name = models.ForeignKey('Component')
        image_name = models.ForeignKey('Image_Type')
    class Image_Meta(models.Model):
        image_component = models.ForeignKey('Image_Component',on_delete=models.CASCADE,)
        component_id = models.IntegerField()
        image_count = models.IntegerField(default=0)
        version = models.CharField(max_length=10)

    class Image(models.Model):
        image_meta = models.ForeignKey('Image_Meta',on_delete=models.CASCADE,)
        image_path = models.URLField(max_length=200)
        order = models.IntegerField()
        version = models.CharField(max_length=10)


    class Feature(models.Model):
        image_component = models.ForeignKey('Image_Component',on_delete=models.CASCADE,)
        feature_value = HStoreField()
        def save(self,*args,**kwargs):
            if Feature.objects.filter(feature_value__has_keys=['size', 'quality' , 'format']):
                super(Feature, self).save(*args, **kwargs)
            else:
                print("Incorrect key entered")

serializers.py

from rest_framework import serializers
from models import Component , Image_Type , Image_Component , Image , Feature , Image_Meta
from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.fields import HStoreField


class ComponentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Component
        field = {'component_name','allowed_extensions'}


class Image_TypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image_Type
        field = {'image_name'}



class Image_ComponentSerializer(serializers.ModelSerializer):
    component_name = ComponentSerializer()
    image_name = Image_TypeSerializer()
    class Meta:
        model = Image_Component
        field = {'component_name','image_name'}

    def create(self, validated_data):
        component_data = validated_data.pop('component_name')
        image_data = validated_data.pop('image_name')
        image_component = Image_Component.objects.create(**validated_data)

        for component_data in component_data:
            Component.objects.create(image_component=image_component, **component_data)

        for image_data in image_data:
            Image_Type.objects.create(image_component=image_component, **image_data)

        return image_component

class Image_MetaSerializer(serializers.ModelSerializer):
    image_component = Image_ComponentSerializer()
    class Meta:
        model = Image_Meta
        field = {'image_component','component_id' , 'image_count', 'version'}

class ImageSerializer(serializers.ModelSerializer):
    image_meta = Image_MetaSerializer()
    class Meta:
        model = Image_Meta
        field = {'image_meta' , 'image_path' , 'order' , 'version'}

class FeatureSerializer(serializers.ModelSerializer):
    image_component = Image_ComponentSerializer()
    class Meta:
        model = Feature
        field = {'image_component' , 'feature_value'}

urls.py

from django.conf.urls import patterns , include , url
from rest_framework.urlpatterns import format_suffix_patterns
from imagedata import views

urlpatterns = patterns('',
    url(r'^api/component$',views.Component.as_view()),
    url(r'^api/image_type$',views.Image_Type.as_view()),
    url(r'^api/image_meta$',views.Image_Meta.as_view()),
    url(r'^api/image_component$',views.Image_Component.as_view()),
    url(r'^api/image$',views.Image.as_view()),
    url(r'^api/feature$',views.Feature.as_view()),
)

urlpatterns = format_suffix_patterns(urlpatterns)

It works fine for component and image_type models i.e, if I try to update these tables I can do for both. But for image_component model whenever I try to update the table I get the error:

AssertionError at /imagedata/api/image_component
The `.create()` method does not support writable nestedfields by default.
Write an explicit `.create()` method for serializer `imagedata.serializers.Image_ComponentSerializer`, or set `read_only=True` on nested serializer fields.
Request Method: POST
Request URL:    http://127.0.0.1:8000/imagedata/api/image_component
Django Version: 1.9
Exception Type: AssertionError
Exception Value:    
The `.create()` method does not support writable nestedfields by default.
Write an explicit `.create()` method for serializer `imagedata.serializers.Image_ComponentSerializer`, or set `read_only=True` on nested serializer fields.
Exception Location: /Library/Python/2.7/site-packages/rest_framework/serializers.py in raise_errors_on_nested_writes, line 724
Python Executable:  /usr/bin/python
Python Version: 2.7.10

The page at http://127.0.0.1:8000/imagedata/api/image_component looks like this : enter image description here

I may be totally wrong but I think the text fields should ask to choose from the set of values of component_name and image_type that are present in component and Image_Type tables respectively but they are not.What am I doing wrong? And how to correct that??

Also there is no problem with Django-Admin. It works just fine.

1 Answer 1

1

As a first thing I want to say that I am pretty sure that the error you got was before adding the .create method on Image_ComponentSerializer.

Since Image_Component is based on 2 foreign keys if you want in the API a select field with both of them, just change your serializer to this (remove .create method since is not needed):

class Image_ComponentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image_Component

So no custom serializer, however this will affect the representation of the Image_Component object, it will show the ids of FK fields. To change this behaviour I override .to_representation method like this:

def to_representation(self, obj):  
    ret = {'component_name': ComponentSerializer(instance=obj.component_name).data,
           'image_name': ImageTypeSerializer(instance=obj.image_name).data}
    return ret

So, the input will be ids of FK and the output will be based on custom serializers for each field.

Sign up to request clarification or add additional context in comments.

1 Comment

I am stuck in another problem..The problem is with the Hstore Field used in the feature_value field in Feature table. While trying to save the feature value in Django-Rest Framework page, the feature value stored is blank. Can you help me to figure out something?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.