[英]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模型中存儲數據。
修改上面的代碼
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)
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
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()
跟隨此鏈接路由器
from rest_framework import routers
router = routers.SimpleRouter()
router.register('users', MyUserViewSet)
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.