Reputation: 1416
models:
class Questionnaire(models.Model):
...
class Question(models.Model):
...
questionnaire = models.ForeignKey('Questionnaire', related_name='questions', blank=True, null=True)
...
serializers:
class QuestionSerializer(serializers.ModelSerializer):
choices = MultipleChoiceSerializer(many=True)
children = RecursiveField(many=True)
class Meta:
model = Question
fields = [
'id',
'text',
'order',
'choices',
#'parent',
'children',
'type',
'category',
'requiredif',
'max_answers',
'min_answers',
]
class QuestionnaireCreateUpdateSerializer(serializers.ModelSerializer):
questions = QuestionSerializer(many=True)
class Meta:
model = Questionnaire
fields = [
'id',
'questions',
'name',
'description',
]
def create(self, validated_data):
print validated_data
...
validated_data using {'name': 'a', 'description': 'b', 'questions': [{'category': 'a', 'min_answers': 1}]}
:
{u'name': u'a', u'questions': [], u'description': u'b'}
simple test:
def test_submit_qnr(self):
self.client.force_login(self.user.user)
qnr2 = {'name': 'a', 'description': 'b', 'questions': [{'category': 'a', 'min_answers': 1}]}
response = self.client.post('/api/qnr/', data=qnr2)
print response.json()
response.json()['questions'].should_not.equal([]) # fails!
JSON response:
{u'description': u'b', u'id': 1, u'questions': [], u'name': u'a'}
I would like to write nested fields and have overridden create
to do so, but there seems to be an issue with validation, in that the data for the nested models is deleted in the validated_data.
I tried printing the validated_data
variable at the top of the create function and for reasons I don't understand the questions
field is an empty list. The relations section in the api-guide documentation shows almost this exact same example. What am I missing?
EDIT1:
The serializer works as expected when tested directly in the shell, but for some reason it fails in the test case
EDIT 2: View:
class QuestionnaireViewSet(viewsets.ModelViewSet):
authentication_classes = [SessionAuthentication, BasicAuthentication, JSONWebTokenAuthentication]
permission_classes = [permissions.IsAuthenticated, ]
queryset = Questionnaire.objects.all()
serializer_class = QuestionnaireCreateUpdateSerializer
URLs:
router = routers.DefaultRouter()
router.register(r'qnr', QuestionnaireViewSet)
urlpatterns = [
...
url(r'^api/', include(router.urls)),
]
Upvotes: 3
Views: 657
Reputation: 19811
Since you followed the example provided in the api-guide and it works in shell I think that the data is not being sent properly.
Django Rest Framework uses APIClient
for testing which is based on Django's Test Client
If you don't provide a content type
the default value is multipart/form-data
If you don’t provide a value for
content_type
, the values indata
will be transmitted with a content type ofmultipart/form-data
. In this case, the key-value pairs in data will be encoded as amultipart
message and used to create thePOST
data payload.
You will need to explicitly specify the format
of the data as json
:
response = self.client.post('/api/qnr/', data=qnr2, format='json')
Upvotes: 2