關於什麼是序列化和反序列化(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