繁体   English   中英

如何在Django Rest框架中实现嵌套序列化器?

[英]How to implement nested serializer in django rest framework?

我正在扩展Django身份验证表的用户模型,并为它实现rest api。

我没有得到相同的实现GET / POST请求的方法。

我的models.py代码是:

class UserProfile(models.Model):
    """User profile model for information about user."""

    users = models.OneToOneField(User)
    phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'")
    phone_number = models.CharField(max_length=100, validators=[phone_regex], blank=True)
    created_timestamp = models.DateTimeField(auto_now_add=True, null=True)
    updated_timestamp = models.DateTimeField(auto_now=True, null=True)

我的serializers.py代码是:

class UserSerializer(serializers.ModelSerializer):
    """Serializer for users."""

    class Meta:
        model = User


class UserProfileSerializer(serializers.ModelSerializer):
    """Serializer for user profiles."""

    users = UserSerializer(many=True)

    class Meta:
        model = UserProfile

    def create(self, validated_data):
        users_data = validated_data.pop('users')
        print 'yes'
        print users_data
        user_profile = UserProfile.objects.create(**validated_data)
        for user_data in users_data:
            user_data, created = User.objects.get_or_create(first_name=user_data['first_name'], last_name=user_data['last_name'],
        username=user_data['username'], password=user_data['password'], email=user_data['email'], is_active=['is_active'])
        user_profile.users.add(user_data)
    return user_profile

我的v1.py代码是:

class UserProfileList(APIView):
    """Get and post user profiles data."""

    def get(self, request, format=None):
        """Get users."""
        user_profiles = UserProfile.objects.all()
        serialized_user_profiles = UserProfileSerializer(user_profiles, many=True)
        return Response(serialized_user_profiles.data)

    def post(self, request, format=None):
        """Post users."""
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

我认为问题出在v1.py文件中。 我想发出GET和POST请求,对于POST请求,我想发送JSON数据。 有人可以帮我实施它吗? 实际上,我想要一个端点来发出POST请求并在User模型和UserProfile模型中存储数据。

修改上面的代码

models.py

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    phone_number = models.CharField(max_length=100, validators=[
    RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'")
    ], blank=True, null=True)
    created_timestamp = models.DateTimeField(auto_now_add=True, null=True)
    updated_timestamp = models.DateTimeField(auto_now=True, null=True)

Serializers.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User

class UserProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)
    class Meta:
        model = UserProfile

    def create(self, validated_data):
        user_data = validated_data.pop('user', None)
        user = User.objects.create_user(**user_data)
        return UserProfile.objects.create(user=user, **validated_data)

   def update(self, instance, validated_data):
       user_dict = validated_data.pop('user', None)
       if user_dict:
           user_obj = instance.user
           for key, value in user_dict.iteritems():
                setattr(user_obj, key, value)
           user_obj.save()
           validated_data["user"] = user_obj
       for key, value in validated_data.iteritems():
           setattr(instance, key, value)
       instance.save()
       return instance

viewsets.py

from rest_framework import mixins
from rest_framework import viewsets

class MyUserViewSet(mixins.UpdateModelMixin,
                    mixins.CreateModelMixin,
                    mixins.ListModelMixin,
                    viewsets.GenericViewSet):

    authentication_classes = (TokenAuthentication, SessionAuthentication)
    permission_classes = (AllowAny, )
    serializer_class = UserProfileSerializer
    queryset = UserProfile.objects.all()

跟随此链接路由器

routers.py

from rest_framework import routers
router = routers.SimpleRouter()
router.register('users', MyUserViewSet)

urls.py

from .routers import router
urlpatterns = patterns(
    url(r'^api/v1/', include(router.urls)),
)

我建议您通过子类化AbstractBaseUser扩展用户模型,这也需要子类化BaseUserManager。 这样,您只需要一个类就可以简化序列化程序。 它还需要BaseUserManager的子类。

自定义用户可以具有任意数量的自定义字段。 通常,以这种方式扩展用户模型比创建与默认用户模型一对一的关系要简单。 它为您节省了一些逻辑和时间。

您可以在此处阅读更多信息: https : //docs.djangoproject.com/ja/1.9/topics/auth/customizing/#specifying-a-custom-user-model

这是一个如何处理BaseUserManager子类的示例:

class MyUserManager(BaseUserManager):
    def create_user(self, email=None, password=None, dateofbirth=None, username=None):
        user = self.model(
            email=MyUserManager.normalize_email(email),    
            dateofbirth=dateofbirth,
            username=username
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, username, dateofbirth, email, password):
        user = self.create_user(email=email,
                    password=password,
                    username=username,
                    dateofbirth=dateofbirth,
                )
        user.is_superuser = True
        user.save(using=self._db)
        return user

这是继承AbstractBaseUser的示例:

class MyUser(AbstractBaseUser):

    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True
    )

    dateofbirth = models.CharField(max_length=30, blank=True)

    is_active = models.BooleanField(default=True)
    is_superuser = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'

    objects = MyUserManager()

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

    def __unicode__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True

    @property
    def is_staff(self):
        return self.is_superuser

为此,您必须在settings.py中设置auth用户模型,以让django应用知道您正在使用自定义用户模型:

AUTH_USER_MODEL = 'myapp.MyUser'

这是简单的部分-序列化器:

class MyUserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = MyUser
        fields = (
            'email',
            'password',
            'dateofbirth',
            'username',
        )

    def create(self, validated_data):
        password = validated_data.pop("password", None)
        email = validated_data.pop("email", None)
        username = validated_data.pop("username", None)
        user = MyUser.objects.create_user(email=email, password=password, username=username, gender=gender, dateofbirth=dateofbirth)
        MyUser.objects.filter(id=user.id).update(**validated_data)
        return user

在使用它时,请不用考虑APIView并使用更简单的ViewSet:

class MyUserViewSet(viewsets.ModelViewSet):
    authentication_classes = (TokenAuthentication, SessionAuthentication)
    permission_classes = (AllowAny, )
    serializer_class = MyUserSerializer

仅此一项,您就可以处理所有的GET,POST,PUT,DELETE请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM