Django REST框架:使用相关字段创建/更新对象

bit*_*eky 10 django rest django-models django-rest-framework

我有两个型号

Auth用户模型和UserProfile

class UserProfile(models.Model):
    user = models.OneToOneField(User, related_name='profile')
    name = models.CharField(_lazy(u'Name'), max_length=255)
Run Code Online (Sandbox Code Playgroud)

我正在使用这些序列化器:

from rest_framework import serializers
from django.contrib.auth.models import User

from oneanddone.users.models import UserProfile

    class UserProfileSerializer(serializers.ModelSerializer):

        class Meta:
            model = UserProfile
            fields = ('name',)


    class UserSerializer(serializers.ModelSerializer):
        profile = serializers.RelatedField()

        class Meta:
            model = User
            fields = ('id', 'username', 'email', 'groups', 'profile')
Run Code Online (Sandbox Code Playgroud)

但在提出要求时

requests.post('http://localhost:8000/api/v1/users/', data={"username": "tester", "email": "tester@gmail.com", "profile": [{"name":"testername"}]} ,headers={'Authorization':'Token d81e33c57b2d9471f4d6849bab3cb233b3b30468'}).text
Run Code Online (Sandbox Code Playgroud)

我使用"null"配置文件字段获取以下对象

u'{"id": 10, "username": "tester", "email": "tester@gmail.com", "groups": [], "profile": null}'
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何创建和更新用户配置文件名称以及auth用户数据.请让我知道如何做到这一点并提供一些相同的例子.

Fiv*_*ver 8

Django REST Framework目前不支持嵌套写入,因此您必须通过覆盖createListCreateAPIView 来创建UserProfile :

class UserList(generics.ListCreateAPIView):
    model = User
    serializer_class = UserSerializer

    def create(self, request, *args, **kwargs):
        data = request.DATA

        # note: transaction.atomic was introduced in Django 1.6
        with transaction.atomic():
            user = User.(
                username=data['username'],
                ...
            )
            user.clean()
            user.save()

            UserProfile.objects.create(
                user=user,
                name=data['profile']['name']
            )

        serializer = UserSerializer(user)
        headers = self.get_success_headers(serializer.data)

        return Response(serializer.data, status=status.HTTP_201_CREATED,
                        headers=headers)
Run Code Online (Sandbox Code Playgroud)

transaction.atomic如果配置文件未成功保存,则使用将回滚用户创建.

编辑

如果您要创建新用户,则可能需要使用该create_user方法.上面的代码旨在显示在一个REST API POST请求中创建模型实例和相关记录的一般情况.


小智 1

实际上 Django Rest Framework 有部分嵌套支持。如果您查看测试套件,您会发现一些。至于 bitgeeky 问题,正如 IRC 上所说,这应该可行。这是一个相关的测试用例: https://github.com/tomchristie/django-rest-framework/blob/2.3.13/rest_framework/tests/test_relations_nested.py#L56

想到这里,我想我曾经犯过这个错误。@bitgeeky 你能确保通过在标头中添加内容类型来发送 json 请求吗?默认情况下,帖子将使用不支持嵌套的表单。