Vietosan
Vietosan

Reputation: 33

How to define models/serializers correctly for Django REST Framework?

We are creating a mobile web application with this stack:

Python Django, SQLite DB Django REST Ionic Cordova Angular JS

This is a quiz application, in which you answer questions from 4 multiple choices. Questions and answers are stored in the database. With the help of REST framework an endpoint has been created.

With this JSON file our Angular JS controller works asynchronously. The problem is defining answers in model.py. It involves an array in an array.

We're trying to get this structure with Django REST:

[
    {
        "question" : "Java was originally developed at _______________",
        "answer"  : [
        {"id"  : 0, "text" : "Sun Microsystems"},
        {"id"  : 1, "text" : "Intel"},
        {"id"  : 2, "text" : "Hewlett-Packard"},
        {"id"  : 3, "text" : "Oracle"}
        ],
        "correct"  : 0
    },
]

And this is what we have:

[
    {
        "question": "Java was originally developed at _______________",
        "answer": [
            {
                "url": "http://127.0.0.1:8000/api/answer/1/",
                "answerid": 0,
                "text": "Sun Microsystems"
            },
            {
                "url": "http://127.0.0.1:8000/api/answer/2/",
                "answerid": 1,
                "text": "Intel"
            },
            {
                "url": "http://127.0.0.1:8000/api/answer/3/",
                "answerid": 2,
                "text": "Hewlett-Packard"
            },
            {
                "url": "http://127.0.0.1:8000/api/answer/4/",
                "answerid": 3,
                "text": "Oracle"
            }
        ],
        "correct": 0
    }
]

Here's our models.py:

from django.db import models

class Answer(models.Model):
    answerid = models.IntegerField()
    text = models.TextField()

class Question(models.Model):
    question = models.CharField(max_length=200)
    answer = models.ManyToManyField(Answer)
    correct = models.IntegerField()

serializer:

from quiz.models import Question, Answer
from rest_framework import routers, serializers, viewsets

class AnswerSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Answer
        fields = ('answerid', 'text')

class QuestionSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Question
        fields = ('question', 'answer', 'correct')
        read_only_fields = ('answer',)
        depth = 1

# ViewSets define the view behavior.
class QuestionViewSet(viewsets.ModelViewSet):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer

class AnswerViewSet(viewsets.ModelViewSet):
    queryset = Answer.objects.all()
    serializer_class = AnswerSerializer

Is it somehow possible to remove the urls in our solution?

Upvotes: 3

Views: 584

Answers (2)

jarussi
jarussi

Reputation: 1589

I believe this will work.

class AnswerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Answer
        fields = ('answerid', 'text')

class QuestionSerializer(serializers.ModelSerializer):

answer = AnswerSerializer(source="answers) 
class Meta:
    model = Question
    fields = ('question', 'answer', 'correct')
    read_only_fields = ('answer',)
    depth = 1

You may need to change the source to correctly get the answers you need.

The serializers.HyperlinkedModelSerializer will automatically insert the url field in your response.

Upvotes: 2

wim
wim

Reputation: 363486

The urls come because you inherit HyperlinkedModelSerializer.

class QuestionSerializer(serializers.HyperlinkedModelSerializer):
    ...

If you don't want them, use a different base class - perhaps just a ModelSerializer.

Upvotes: 2

Related Questions