I
I
Ilya2015-11-05 00:05:20
Django
Ilya, 2015-11-05 00:05:20

How to properly serialize an object?

How to properly serialize an object?
models.py

# -*- coding: utf-8 -*-
from django.db import models

class ingridient(models.Model):
    name = models.CharField(verbose_name = u'Ингридиент',max_length=30, unique=True)
    slug = models.SlugField(verbose_name = u'URL',primary_key=True, max_length=250, unique=True, default='SOME STRING')
    def __unicode__(self):
        return self.name

class recipe(models.Model):
    name = models.CharField(verbose_name = u'Рецепт',max_length=30,unique=True)
    ingridients = models.ManyToManyField(ingridient, verbose_name=u'Ингридиенты')
    slug = models.SlugField(verbose_name = u'URL',primary_key=True, max_length=250, unique=True, default='SOME STRING')

    def get_ing(obj):
        return ','.join(obj.ingridients.values_list('name', flat=True))
    get_ing.short_description = 'Ингридиенты'

    def __unicode__(self):
        return self.name

views.py
class RecipeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = recipe
        #fields = ('url', 'name')

# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
    queryset = recipe.objects.all()
    serializer_class = RecipeSerializer

urls.py
url(r'^api/$', include('rest_framework.urls', namespace='rest_framework')),
urlpatterns = format_suffix_patterns(urlpatterns)

Am I serializing the objects correctly?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim Dunayevsky, 2015-11-05
@nuBacuk

I would write like this:

from django.db import models


class Ingridient(models.Model):

    name = models.CharField(
        max_length=30,
        unique=True,
        db_index=True
    )

    class Meta:
        db_table = 'ingridient'
        ordering = [ 'name' ]


class Recipe(models.Model):

    name = models.CharField(
        max_length=30,
        unique=True,
        db_index=True
    )

    ingridients = models.ManyToManyField(
        Ingridient
    )

    class Meta:
        db_table = 'recipe'
        ordering = [ 'name' ]

from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField
from .models import Ingridient, Recipe


class IngridientSerializer(ModelSerializer):

    class Meta:
        model = Ingridient


class RecipeReadListSerializer(ModelSerializer):

    class Meta:
        model = Recipe
        exclude = ['ingridients']


class RecipeReadDetailSerializer(ModelSerializer):

    ingridients = IngridientSerializer(
        many=True
    )

    class Meta:
        model = Recipe


class RecipeWriteSerializer(ModelSerializer):

    ingridients = PrimaryKeyRelatedField(
        queryset=Ingridient.objects.all(),
        many=True,
        default=[]
    )

    class Meta:
        model = Recipe

from rest_framework.viewsets import ModelViewSet

from .serializers import IngridientSerializer, RecipeReadListSerializer, RecipeReadDetailSerializer, RecipeWriteSerializer
from .models import Ingridient, Recipe
from rest_framework.permissions import AllowAny


class IngridientViewSet(ModelViewSet):

    queryset = Ingridient.objects.all()

    serializer_class = IngridientSerializer

    permission_classes = [
        AllowAny
    ]

    class Meta:
        model = Ingridient


class RecipeViewSet(ModelViewSet):

    queryset = Recipe.objects.all()

    permission_classes = [
        AllowAny
    ]

    def get_serializer_class(self):
        if self.request.method == 'GET':
            if self.action == 'list':
                return RecipeReadListSerializer
            return RecipeReadDetailSerializer
        return RecipeWriteSerializer

from rest_framework.routers import SimpleRouter
from .views import IngridientViewSet, RecipeViewSet

router = SimpleRouter()
router.register(r'ingridients', IngridientViewSet, base_name='ingridients')
router.register(r'recipies', RecipeViewSet, base_name='recipe')

urlpatterns = router.urls

As for using SlugField , I'm not entirely sure that they are needed, because the API in this case will be simple, the list of its URLs is nowhere simpler at all, however, I think you can add them at any time you need.
Why are there three serializers to serialize recipes?
When you receive a list of all recipes, you usually do not need to immediately receive all the ingredients. In any case, in my applications, I load a full copy of the model only when viewing in detail, and in lists, some of the fields are hidden at the API level. Needless to say, when serializing users, several serializers are simply necessary in order not to display the password when the object is received, but to be able to update it when writing?
The serializer for reading the details just emits nested objects when it receives the recipe model - the ingridients field will contain an array of fully serialized Ingridient objects .
The third serializer is only used to create or update Recipe records. To fill in the ingredients, you need to pass a list of their id. DRF will check for the existence of the relevant models and take care of the rest.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question