簡體   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