it外包人員有多慘涇縣網(wǎng)站seo優(yōu)化排名
本文從分析現(xiàn)在流行的前后端分離Web應(yīng)用模式說(shuō)起,然后介紹如何設(shè)計(jì)REST API,通過(guò)使用Django來(lái)實(shí)現(xiàn)一個(gè)REST API為例,明確后端開發(fā)REST API要做的最核心工作,然后介紹Django REST framework能幫助我們簡(jiǎn)化開發(fā)REST API的工作。
全套筆記直接地址: 請(qǐng)移步這里
共 5 章,24 子模塊
DRF工程搭建
見識(shí)DRF的魅力
我們?nèi)砸栽趯W(xué)習(xí)Django框架時(shí)使用的圖書英雄為案例,使用Django REST framework快速實(shí)現(xiàn)圖書的REST API。
1. 創(chuàng)建序列化器
在booktest應(yīng)用中新建serializers.py用于保存該應(yīng)用的序列化器。
創(chuàng)建一個(gè)BookInfoSerializer用于序列化與反序列化。
class BookInfoSerializer(serializers.ModelSerializer):"""圖書數(shù)據(jù)序列化器"""class Meta:model = BookInfofields = '__all__'
- model 指明該序列化器處理的數(shù)據(jù)字段從模型類BookInfo參考生成
- fields 指明該序列化器包含模型類中的哪些字段,'all’指明包含所有字段
2. 編寫視圖
在booktest應(yīng)用的views.py中創(chuàng)建視圖BookInfoViewSet,這是一個(gè)視圖集合。
from rest_framework.viewsets import ModelViewSet
from .serializers import BookInfoSerializer
from .models import BookInfoclass BookInfoViewSet(ModelViewSet):queryset = BookInfo.objects.all()serializer_class = BookInfoSerializer
- queryset 指明該視圖集在查詢數(shù)據(jù)時(shí)使用的查詢集
- serializer_class 指明該視圖在進(jìn)行序列化或反序列化時(shí)使用的序列化器
3. 定義路由
在booktest應(yīng)用的urls.py中定義路由信息。
from . import views
from rest_framework.routers import DefaultRouterurlpatterns = [...
]router = DefaultRouter() # 可以處理視圖的路由器
router.register('books', views.BookInfoViewSet, name='books') # 向路由器中注冊(cè)視圖集urlpatterns += router.urls # 將路由器中的所以路由信息追到到django的路由列表中
4. 運(yùn)行測(cè)試
運(yùn)行當(dāng)前程序(與運(yùn)行Django一樣)
python manage.py runserver
在瀏覽器中輸入網(wǎng)址127.0.0.1:8000,可以看到DRF提供的API Web瀏覽頁(yè)面:
1)點(diǎn)擊鏈接127.0.0.1:8000/books/ 可以訪問(wèn)所有數(shù)據(jù)的接口,呈現(xiàn)如下頁(yè)面:
2)在頁(yè)面底下表單部分填寫圖書信息,可以訪問(wèn)添加新圖書的接口,保存新書:
點(diǎn)擊POST后,返回如下頁(yè)面信息:
3)在瀏覽器中輸入網(wǎng)址127.0.0.1:8000/books/1/,可以訪問(wèn)單一圖書信息的接口(id為1的圖書),呈現(xiàn)如下頁(yè)面:
4)在頁(yè)面底部表單中填寫圖書信息,可以訪問(wèn)修改圖書的接口:
點(diǎn)擊PUT,返回如下頁(yè)面信息:
5)點(diǎn)擊DELETE按鈕,可以訪問(wèn)刪除圖書的接口:
返回,如下頁(yè)面:
至此,是不是發(fā)現(xiàn)Django REST framework很好用!
Serializer序列化器
序列化器的作用:
- 進(jìn)行數(shù)據(jù)的校驗(yàn)
- 對(duì)數(shù)據(jù)對(duì)象進(jìn)行轉(zhuǎn)換
定義Serializer
1. 定義方法
Django REST framework中的Serializer使用類來(lái)定義,須繼承自rest_framework.serializers.Serializer。
例如,我們已有了一個(gè)數(shù)據(jù)庫(kù)模型類BookInfo
class BookInfo(models.Model):btitle = models.CharField(max_length=20, verbose_name='名稱')bpub_date = models.DateField(verbose_name='發(fā)布日期', null=True)bread = models.IntegerField(default=0, verbose_name='閱讀量')bcomment = models.IntegerField(default=0, verbose_name='評(píng)論量')image = models.ImageField(upload_to='booktest', verbose_name='圖片', null=True)
我們想為這個(gè)模型類提供一個(gè)序列化器,可以定義如下:
class BookInfoSerializer(serializers.Serializer):"""圖書數(shù)據(jù)序列化器"""id = serializers.IntegerField(label='ID', read_only=True)btitle = serializers.CharField(label='名稱', max_length=20)bpub_date = serializers.DateField(label='發(fā)布日期', required=False)bread = serializers.IntegerField(label='閱讀量', required=False)bcomment = serializers.IntegerField(label='評(píng)論量', required=False)image = serializers.ImageField(label='圖片', required=False)
**注意:serializer不是只能為數(shù)據(jù)庫(kù)模型類定義,也可以為非數(shù)據(jù)庫(kù)模型類的數(shù)據(jù)定義。**serializer是獨(dú)立于數(shù)據(jù)庫(kù)之外的存在。
2. 字段與選項(xiàng)
常用字段類型:
字段 | 字段構(gòu)造方式 |
---|---|
**BooleanField** | BooleanField() |
**NullBooleanField** | NullBooleanField() |
**CharField** | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
**EmailField** | EmailField(max_length=None, min_length=None, allow_blank=False) |
**RegexField** | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
**SlugField** | SlugField(max_length=50, min*length=None, allow_blank=False) 正則字段,驗(yàn)證正則模式 [a-zA-Z0-9*-]+ |
**URLField** | URLField(max_length=200, min_length=None, allow_blank=False) |
**UUIDField** | UUIDField(format='hex_verbose') format: 1) `'hex_verbose'` 如`"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"` 2) `'hex'` 如 `"5ce0e9a55ffa654bcee01238041fb31a"` 3)`'int'` - 如: `"123456789012312313134124512351145145114"` 4)`'urn'` 如: `"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"` |
**IPAddressField** | IPAddressField(protocol='both', unpack_ipv4=False, **options) |
**IntegerField** | IntegerField(max_value=None, min_value=None) |
**FloatField** | FloatField(max_value=None, min_value=None) |
**DecimalField** | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位數(shù) decimal_palces: 小數(shù)點(diǎn)位置 |
**DateTimeField** | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
**DateField** | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
**TimeField** | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
**DurationField** | DurationField() |
**ChoiceField** | ChoiceField(choices) choices與Django的用法相同 |
**MultipleChoiceField** | MultipleChoiceField(choices) |
**FileField** | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
**ImageField** | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
**ListField** | ListField(child=, min_length=None, max_length=None) |
**DictField** | DictField(child=) |
選項(xiàng)參數(shù):
參數(shù)名稱 | 作用 |
---|---|
**max_length** | 最大長(zhǎng)度 |
**min_lenght** | 最小長(zhǎng)度 |
**allow_blank** | 是否允許為空 |
**trim_whitespace** | 是否截?cái)嗫瞻鬃址?/td> |
**max_value** | 最小值 |
**min_value** | 最大值 |
通用參數(shù):
參數(shù)名稱 | 說(shuō)明 |
---|---|
**read_only** | 表明該字段僅用于序列化輸出,默認(rèn)False |
**write_only** | 表明該字段僅用于反序列化輸入,默認(rèn)False |
**required** | 表明該字段在反序列化時(shí)必須輸入,默認(rèn)True |
**default** | 反序列化時(shí)使用的默認(rèn)值 |
**allow_null** | 表明該字段是否允許傳入None,默認(rèn)False |
**validators** | 該字段使用的驗(yàn)證器 |
**error_messages** | 包含錯(cuò)誤編號(hào)與錯(cuò)誤信息的字典 |
**label** | 用于HTML展示API頁(yè)面時(shí),顯示的字段名稱 |
**help_text** | 用于HTML展示API頁(yè)面時(shí),顯示的字段幫助提示信息 |
3. 創(chuàng)建Serializer對(duì)象
定義好Serializer類后,就可以創(chuàng)建Serializer對(duì)象了。
Serializer的構(gòu)造方法為:
Serializer(instance=None, data=empty, **kwarg)
說(shuō)明:
1)用于序列化時(shí),將模型類對(duì)象傳入instance參數(shù)
2)用于反序列化時(shí),將要被反序列化的數(shù)據(jù)傳入data參數(shù)
3)除了instance和data參數(shù)外,在構(gòu)造Serializer對(duì)象時(shí),還可通過(guò)context參數(shù)額外添加數(shù)據(jù),如
serializer = AccountSerializer(account, context={'request': request})
通過(guò)context參數(shù)附加的數(shù)據(jù),可以通過(guò)Serializer對(duì)象的context屬性。
序列化使用
我們?cè)赿jango shell中來(lái)學(xué)習(xí)序列化器的使用。
python manage.py shell
1 基本使用
1) 先查詢出一個(gè)圖書對(duì)象
from booktest.models import BookInfobook = BookInfo.objects.get(id=2)
2) 構(gòu)造序列化器對(duì)象
from booktest.serializers import BookInfoSerializerserializer = BookInfoSerializer(book)
3)序列化數(shù)據(jù)
通過(guò)data屬性可以序列化后的數(shù)據(jù)
serializer.data# {'id': 2, 'btitle': '天龍八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}
4)如果要被序列化的是包含多條數(shù)據(jù)的查詢集QuerySet,可以通過(guò)添加many=True參數(shù)補(bǔ)充說(shuō)明
book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data# [OrderedDict([('id', 2), ('btitle', '天龍八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', N]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]), OrderedDict([('id', 4), ('btitle', '雪山飛狐'), ('bpub_date', '1987-11-11'), ('bread', 58), ('bcomment', 24), ('ima None)]), OrderedDict([('id', 5), ('btitle', '西游記'), ('bpub_date', '1988-01-01'), ('bread', 10), ('bcomment', 10), ('im', 'booktest/xiyouji.png')])]
2 關(guān)聯(lián)對(duì)象嵌套序列化
如果需要序列化的數(shù)據(jù)中包含有其他關(guān)聯(lián)對(duì)象,則對(duì)關(guān)聯(lián)對(duì)象數(shù)據(jù)的序列化需要指明。
例如,在定義英雄數(shù)據(jù)的序列化器時(shí),外鍵hbook(即所屬的圖書)字段如何序列化?
我們先定義HeroInfoSerialzier除外鍵字段外的其他部分
class HeroInfoSerializer(serializers.Serializer):"""英雄數(shù)據(jù)序列化器"""GENDER_CHOICES = ((0, 'male'),(1, 'female'))id = serializers.IntegerField(label='ID', read_only=True)hname = serializers.CharField(label='名字', max_length=20)hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性別', required=False)hcomment = serializers.CharField(label='描述信息', max_length=200, required=False, allow_null=True)
對(duì)于關(guān)聯(lián)字段,可以采用以下幾種方式:
1) PrimaryKeyRelatedField
此字段將被序列化為關(guān)聯(lián)對(duì)象的主鍵。
hbook = serializers.PrimaryKeyRelatedField(label='圖書', read_only=True)
或
hbook = serializers.PrimaryKeyRelatedField(label='圖書', queryset=BookInfo.objects.all())
指明字段時(shí)需要包含read_only=True或者queryset參數(shù):
- 包含read_only=True參數(shù)時(shí),該字段將不能用作反序列化使用
- 包含queryset參數(shù)時(shí),將被用作反序列化時(shí)參數(shù)校驗(yàn)使用
使用效果:
from booktest.serializers import HeroInfoSerializer
from booktest.models import HeroInfo
hero = HeroInfo.objects.get(id=6)
serializer = HeroInfoSerializer(hero)
serializer.data# {'id': 6, 'hname': '喬峰', 'hgender': 1, 'hcomment': '降龍十八掌', 'hbook': 2}
2)使用關(guān)聯(lián)對(duì)象的序列化器
hbook = BookInfoSerializer()
使用效果
{'id': 6, 'hname': '喬峰', 'hgender': 1, 'hcomment': '降龍十八掌', 'hbook': OrderedDict([('id', 2), ('btitle', '天龍八部')te', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', None)])}
3) StringRelatedField
此字段將被序列化為關(guān)聯(lián)對(duì)象的字符串表示方式(即__str__方法的返回值)
hbook = serializers.StringRelatedField(label='圖書')
使用效果
{'id': 6, 'hname': '喬峰', 'hgender': 1, 'hcomment': '降龍十八掌', 'hbook': '天龍八部'}
3 many參數(shù)
如果關(guān)聯(lián)的對(duì)象數(shù)據(jù)不是只有一個(gè),而是包含多個(gè)數(shù)據(jù),如想序列化圖書BookInfo數(shù)據(jù),每個(gè)BookInfo對(duì)象關(guān)聯(lián)的英雄HeroInfo對(duì)象可能有多個(gè),此時(shí)關(guān)聯(lián)字段類型的指明仍可使用上述幾種方式,只是在聲明關(guān)聯(lián)字段時(shí),多補(bǔ)充一個(gè)many=True參數(shù)即可。
此處僅拿PrimaryKeyRelatedField類型來(lái)舉例,其他相同。
在BookInfoSerializer中添加關(guān)聯(lián)字段:
class BookInfoSerializer(serializers.Serializer):"""圖書數(shù)據(jù)序列化器"""id = serializers.IntegerField(label='ID', read_only=True)btitle = serializers.CharField(label='名稱', max_length=20)bpub_date = serializers.DateField(label='發(fā)布日期', required=False)bread = serializers.IntegerField(label='閱讀量', required=False)bcomment = serializers.IntegerField(label='評(píng)論量', required=False)image = serializers.ImageField(label='圖片', required=False)heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增
使用效果:
from booktest.serializers import BookInfoSerializer
from booktest.models import BookInfo
book = BookInfo.objects.get(id=2)
serializer = BookInfoSerializer(book)
serializer.data# {'id': 2, 'btitle': '天龍八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None, 'heroinfo_set': [6,8, 9]}