关于什么是序列化和反序列化(4) 【紧跟前一节】
【转
https://blog.csdn.net/YangHeng816/article/details/78534186
POST 请求---------> 反序列化过程------->
deserializer: Json → native datatype【data = JSONParser().parse(BytesIO(content))】 → isntance【serializer = SnippetSerializer(data=data)
serializer.is_valid()# True serializer.save()】
GET 请求 ----------> 序列化过程---------->
serilization : isntance(django 模型实例) → native datatype(python 原生数据类型)【serializer.data】 → Json【JSONRenderer().render(serializer.data)】,将model实例的转为json格式response出去。
从REST的设计原则看,它实际上是为了满足客户端的需求,现在的web后端与客户端(ios/android)打交道的多,这样的格式化response更便于它们解析。换句话说就是:将response打包成某种格式(如JSON)的东西。
】
复制代码
官方文档解释
SerializerMethodField 这是一个只读字段。
它通过调用它所连接的序列化器类的方法来获取它的值 它可以用于向对象的序列化表示添加任何类型的数据
Signature: SerializerMethodField(method_name=None)
method_name——要调用的序列化器上的方法的名称。
如果不包括此缺省值,则get_<field_name>。
method_name参数引用的序列化器方法应该接受一个参数(除了self),这个参数是被序列化的对象。
它应该返回您希望包含在对象的序列化表示中的任何内容
现在我们来试试
完整实例代码
models.py
from django.db import models
# Create your models here.
from django.contrib.auth.models import AbstractBaseUser
class MyUsers(models.Model):
#REQUIRED_FIELDS = ('name',)
#USERNAME_FIELD = ('name')
groups = models.ForeignKey(
'Groups',
null=False,
blank=False,
related_name='myusers',
on_delete=models.CASCADE
)
name = models.CharField(
null=False,
blank=False,
max_length=125,
)
email = models.EmailField(
null=False,
blank=False,
max_length=125,
)
url = models.URLField(
null=False,
blank=True,
max_length=125,
)
class Groups(models.Model):
name = models.CharField(
null=False,
blank=False,
max_length=125,
)
url = models.URLField(
null=False,
blank=True,
max_length=125,
)
class Ip(models.Model):
user = models.ForeignKey(
'MyUsers',
null=False,
blank=False,
related_name='ips',
on_delete=models.CASCADE
)
group = models.ForeignKey(
'Groups',
null=False,
blank=True,
related_name='ips',
on_delete=models.CASCADE
)
ip_addr = models.GenericIPAddressField(
blank=False,
null=False,
)
serializers.py
from django.contrib.auth.models import User, Group
from rest_framework import serializers
from accounts.models import Ip
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'groups', 'user')
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ('url', 'name')
class IpSerializer(serializers.HyperlinkedModelSerializer):
#SerializerMethodField(): Serialization and deserialization
group = serializers.SerializerMethodField()
user = serializers.SerializerMethodField()
class Meta:
model = Ip
fields = ('user', 'ip_addr', 'group')
def get_group(self, obj):# 调用所连接的序列化器类的方法
print(obj)
group = obj.group
print(group)
print(group.url)
return{'url': group.url,
'name': group.name,
}
def get_user(self, obj):# 向对象的序列化表示添加任何类型的数据
print(obj)
user = obj.user
print(user)
if user:
print(1)
return {
'name': user.name + ' ' + 'hello'
}
views.py
from django.shortcuts import render
# Create your views here.
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from accounts.serializers import UserSerializer, GroupSerializer, IpSerializer
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from knox.auth import TokenAuthentication
from knox.models import AuthToken
from rest_framework.permissions import IsAuthenticated, AllowAny
from accounts.models import Ip
class UserViewSet(viewsets.ModelViewSet):
authentication_classes = (
TokenAuthentication,
)
permission_classes = (AllowAny,)
queryset = User.objects.all().order_by('-date_joined').prefetch_related('groups')
serializer_class = UserSerializer
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
auth_token = AuthToken.objects.create(user)
# print(auth_token)
return Response(
{
"email": user.email,
"token": auth_token,
"id": user.id,
#"key": auth_token.key,
}
)
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
self.token = AuthToken.objects.create(user)
print(request.user)
self.headers = self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.token)
# token is setted into the requested headers
# token = Token.objects.create(user=user)
print(self.token.key)
"""
# class UserViewSet(viewsets.ModelViewSet):
# """
# 允许用户查看或编辑的API路径。
# """
# queryset = User.objects.all().order_by('-date_joined')
# serializer_class = UserSerializer
# def Post(self, request, *args, **kwargs):
# serializer = self.get_serializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# user = serializer.save()
# token = Token.objects.create(user=user)
# print(token.key)
# # auth_token = AuthToken.objects.create(user)
# # print(auth_token.key)
# return Response(
# {
# "name": user.username,
# "token": token,
# "id": user.id,
# }
# )
#
class GroupViewSet(viewsets.ModelViewSet):
"""
允许组查看或编辑的API路径。
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer
class IpViewSet(viewsets.ModelViewSet):
"""
允许组查看或编辑的API路径。
"""
queryset = Ip.objects.all()
serializer_class = IpSerializer
前面的都是项目下的应用Floral/
Floral/
accounts下的文件
下面是项目Floral下的文件
Floral/urls.py(注意:项目下的url)
from django.conf.urls import url, include
from rest_framework import routers
from accounts import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
router.register(r'ips', views.IpViewSet)
# 使用自动URL路由连接我们的API。
# 另外,我们还包括支持浏览器浏览API的登录URL。
urlpatterns = [
url(r'api/auth/', include('knox.urls')),
url(r'^', include(router.urls)),
# url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
复制代码
重点要解释的部分 通过SerializerMethodField实现序列化 group是Ip表中的外键,关联MyUser模型 通过get_group()方法来设置返回的数据 user则是自定义的序列化字段 通过get_user()方法来设置返回的数据
class IpSerializer(serializers.HyperlinkedModelSerializer):
#SerializerMethodField(): Serialization and deserialization
group = serializers.SerializerMethodField()
user = serializers.SerializerMethodField()
class Meta:
model = Ip
fields = ('user', 'ip_addr', 'group')
def get_group(self, obj):# 调用所连接的序列化器类的方法
print(obj)
group = obj.group
print(group)
print(group.url)
return{'url': group.url,
'name': group.name,
}
def get_user(self, obj):# 向对象的序列化表示添加任何类型的数据
print(obj)
user = obj.user
print(user)
if user:
print(1)
return {
'name': user.name + ' ' + 'hello'
}
复制代码
执行python manage.py runserver后,访问网址http://127.0.0.1:8000/ips/,出现的结果
Django version 2.0.5, using settings 'Floral.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
(0.002) SELECT "accounts_ip"."id", "accounts_ip"."user_id", "accounts_ip"."group_id", "accounts_ip"."ip_addr" FROM "accounts_ip"; args=()
Ip object (1)
(0.001) SELECT "accounts_myusers"."id", "accounts_myusers"."groups_id", "accounts_myusers"."name", "accounts_myusers"."email", "accounts_myusers"."url" FROM "accounts_myusers" WHERE "accounts_myusers"."id" = 1; args=(1,)
MyUsers object (1)
1
Ip object (1)
(0.001) SELECT "accounts_groups"."id", "accounts_groups"."name", "accounts_groups"."url" FROM "accounts_groups" WHERE "accounts_groups"."id" = 1; args=(1,)
Groups object (1)
http://www.baidu.com
[31/May/2018 07:51:52] "GET /ips/ HTTP/1.1" 200 105
复制代码
使用postman测试的结果 图: https://note.youdao.com/yws/res/32197/WEBRESOURCE349824a3428c554357e2b7a7c27f7792