简体   繁体   English

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

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

I was extending User model of django auth table and implementing rest api for the same. 我正在扩展Django身份验证表的用户模型,并为它实现rest api。

I'm not getting how to implement GET/POST request for the same. 我没有得到相同的实现GET / POST请求的方法。

My models.py code is: 我的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)

My serializers.py code is: 我的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

My v1.py code is : 我的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)

I think the problem is in v1.py file. 我认为问题出在v1.py文件中。 I want to make GET and POST request, for POST request I want to send JSON data. 我想发出GET和POST请求,对于POST请求,我想发送JSON数据。 Can someone help me out in its implementation. 有人可以帮我实施它吗? Actually, I want single endpoint for making POST request and storing data in both User model and UserProfile model. 实际上,我想要一个端点来发出POST请求并在User模型和UserProfile模型中存储数据。

Modifying the above code 修改上面的代码

models.py 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 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 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()

Follow this link routers 跟随此链接路由器

routers.py routers.py

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

urls.py urls.py

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

I would suggest you extend the User model by subclassing AbstractBaseUser, which requires also subclassing BaseUserManager. 我建议您通过子类化AbstractBaseUser扩展用户模型,这也需要子类化BaseUserManager。 That way you will be able to simplify your serializer by having only one class for it. 这样,您只需要一个类就可以简化序列化程序。 It also requires subclassing of the BaseUserManager. 它还需要BaseUserManager的子类。

Custom users can have as many custom fields as you want. 自定义用户可以具有任意数量的自定义字段。 It is generally simpler to extend the user model this way than creating a one-to-one relation to the default user model. 通常,以这种方式扩展用户模型比创建与默认用户模型一对一的关系要简单。 It saves you some logic and some time. 它为您节省了一些逻辑和时间。

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

Here's an example of how you would do subclass BaseUserManager: 这是一个如何处理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

Here's an example of subclassing AbstractBaseUser: 这是继承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

For this to work you will have to set the auth user model in your settings.py, to let your django app know you are using a custom user model: 为此,您必须在settings.py中设置auth用户模型,以让django应用知道您正在使用自定义用户模型:

AUTH_USER_MODEL = 'myapp.MyUser'

Here's the simple part - the serializer: 这是简单的部分-序列化器:

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

While you're at it, forget about the APIView and use the much simpler ViewSet: 在使用它时,请不用考虑APIView并使用更简单的ViewSet:

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

And with this alone you have GET, POST, PUT, DELETE requests all handled. 仅此一项,您就可以处理所有的GET,POST,PUT,DELETE请求。

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

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