nuBacuk
@nuBacuk
Python/Linux

Как правильно сериализовать объект?

Как правильно сериализовать объект?

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)


Правильно ли я сериализирую объекты?
  • Вопрос задан
  • 277 просмотров
Решения вопроса 1
dunmaksim
@dunmaksim
Технический писатель
Я бы написал так:
models.py
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' ]


serializers.py
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


views.py
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


urls.py
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


Насчёт использования SlugField не совсем уверен, что они нужны, ведь API в данном случае будет простым, список его URL вообще проще некуда, впрочем, я думаю, добавить их вы сможете в любое нужное время.
Зачем для сериализации рецептов целых три сериализатора?
При получении списка всех рецептов как правило не нужно сразу же получать и все ингридиенты. Во всяком случае, в моих приложениях я делаю подгрузку полной копии модели только при детальном просмотре, а в списках часть полей скрыта на уровне API. Надо ли говорить, что при сериализации пользователей несколько сериализаторов просто необходимы, чтобы не выводить пароль при получении объекта, но иметь возможность его обновлять при записи?
Сериализатор для чтения деталей как раз выдаёт вложенные объекты при получении модели рецепта - в поле ingridients будет массив полностью сериализованных объектов Ingridient.
Третий сериализатор используется только для создания записей типа Recipe или их обновления. Для заполнения ингридиентов нужно передать список их id. DRF сам проверит существование соответствующих моделей и выполнит все остальные действия.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы