djangorestframework怎么这么好用!
一年前就已經用過restframework, 當時覺得這個只是給web框架打輔助的, 他能實現的我也都實現(可能沒有那么好用, 嘿嘿)
但是我有一種東西叫做效率, 時間就是金錢, 別人造好的就直接用就可以了, 自己其實沒必要在去重復.
最近寫一個調查問卷系統, 利用了以下知識點
1. django
2.?restframework(重點重點重點)
3. Vue
4. axios
5. ..............
從這個項目中我對restframework有了重新的認識, 互聯網的精神就是共享, 所以就分享出來了
restframework的序列化器
當項目的架構為前后端分離時, 前后端的數據交互就變的尤為的重要, restframework的序列化過程無外乎一下6步:
1. 獲取數據集合(queryset)
2. 獲取序列化器
3. 過濾, 排序
4. 分頁
5. 對處理好的數據進行進行序列化
5. 響應序列化結果
這些都是最基本的步驟, 但是在每一步中都蘊藏了大量的小技術, 利用這些小技術, 也許你正在頭疼的一小問題就能找到答案, 哈哈, 細節決定成敗
選擇性的對字段進行序列化
官方是這樣說的
For example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so
王氏翻譯:?例如,如果您希望能夠在初始化序列化器時設置序列化器應該使用哪些字段,您可以創建這樣的序列化器類:
這個類就長這樣
class DynamicFieldsModelSerializer(serializers.ModelSerializer):"""A ModelSerializer that takes an additional `fields` argument thatcontrols which fields should be displayed."""def __init__(self, *args, **kwargs):# Don't pass the 'fields' arg up to the superclassfields = kwargs.pop('fields', None)# Instantiate the superclass normallysuper(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)if fields is not None:# Drop any fields that are not specified in the `fields` argument.allowed = set(fields)existing = set(self.fields)for field_name in existing - allowed:self.fields.pop(field_name)
之后你的序列化器就可以繼承這個類了, 但是要注意這個類是在ModelSerializer之上的
下面就是使用方法
序列化器
class BookSerializers(DynamicFieldsModelSerializer):class Meta:model = models.Bookfields = "__all__"
在視圖中使用序列化器
class TestView(APIView):def get(self, request, *args, **kwargs):queryset = models.Book.objects.all()serializer = serializers.BookSerializers(queryset, many=True, fields=("id", "title", "price"))# fields: 指定要序列化的字段return Response(serializer.data)
?自定義field
雖然內置有很多的字段類型, 但是從實際的開發角度來說, 內置的都是一些普遍使用的字段, 再生產環境中結合實際問題, 那就需要我們自己定義字段了
現在就有一種實際需求
公司購買了多臺CDN服務器, 從來存放圖片等靜態資源, 現在有一個問題, 假如某一天公司換了CDN, 那么之前代碼中的圖片鏈接都要修改一遍嗎, 肯定不行
其實解決這個問題的方法有多種, 下面就使用自定義字段來解決這個問題
1. 創建一個自定義字段
class ImagePathField(fields.Field):def __init__(self, cdn_host, *args, **kwargs):super(ImagePathField, self).__init__(*args, **kwargs)self.cdn_host = cdn_host # 封裝CDN主機def to_representation(self, value):"""序列化時這個方法會被執行:param value::return:"""return "{}/{}".format(self.cdn_host, value) # 構建完整的鏈接地址, 返回值將作為數據源def to_internal_value(self, data):pass
2. 在序列化器中使用自定義的字段
class BookSerializers(DynamicFieldsModelSerializer):title = fields.ImagePathField(settings.CND_HOST) # 使用自定義的字段, 還可以傳遞source參數, 就相當于執行ORM, 寫什么就對這個對象"."什么class Meta:model = models.Bookfields = "__all__"
3. 驗證序列化結果
方法字段
除了上面的自定義字段, 還有一種方法字段方法字段, 這種字段也能夠起到自定義的效果
1. 在序列化器中使用方法字段
class BookSerializers(DynamicFieldsModelSerializer):authors = serializers.SerializerMethodField() # 使用方法字段class Meta:model = models.Bookfields = "__all__"def get_authors(self, value):"""對authors這個字段進行序列化時, 會調用get_字段這個方法, 這個方法的返回值將作為數據源:param value::return:"""author_str = ""for author in value.authors.all():author_str += "%s-%s " % (author.name, str(author.age))return author_str
2. 在視圖中對數據進行序列化
class TestView(APIView):def get(self, request, *args, **kwargs):queryset = models.Book.objects.all()serializer = serializers.BookSerializers(queryset, many=True, fields=("id", "title", "price", "authors"))# fields: 指定要序列化的字段return Response(serializer.data)
3. 驗證序列化結果
?內置的時間字段?DateTimeField
在處理時間數據時, 讓人頭疼就是時間的格式, 不同的位置可能顯示的格式不一樣, 在DRF中內置了時間字段, 可以對時間數據做格式化
1. 在序列化器中使用時間字段
class BookSerializers(DynamicFieldsModelSerializer):pub_date = serializers.DateTimeField(format="%Y-%m-%d %X") # 使用時間字段, 指定時間格式class Meta:model = models.Bookfields = "__all__"
2. 驗證序列化結果
內置字符串字段??CharField
字符串是用的最多的數據類型, 當你需要從一個ORM對象關聯的另外一種表中取某某一個字段時, 那么你就可以使用CharField
1. 在序列器中使用CharField
很重要的一個參數就是source, 他可以執行ORM操作
還有一個參數就會default, 可以給一個默認值
class BookSerializers(DynamicFieldsModelSerializer):publish = serializers.CharField(source="publish.address") # source默認就是publish, 不需要寫, 使用"."的方式進行ORM操作class Meta:model = models.Bookfields = "__all__"
2. 驗證序列化結果
嵌套的序列化器
當表結構很深的時候, 構建數據往往是很麻煩的事情, 而且考慮到網絡傳輸的效率問題, 還要盡量的減少無用的數據傳輸, 只傳輸必須的數據
這樣一來就需要在序列化的時候下功夫了.
ORM有外鍵和多對多, 一對一等數據類型, 對比著序列化器, 就是序列化一個元素, 序列化多個元素而已
下面是我在調查問卷系統中的一個嵌套的序列化器
class ChoicesSerializer(DynamicFieldsModelSerializer):"""4. 用于獲取問題所對應的選項的答案和答案所對應的分值的序列化器"""class Meta:model = models.SurveyChoicesfields = "__all__"class QuestionSerializer(DynamicFieldsModelSerializer):"""3. 獲取問卷調查模板的所有問題"""survey = serializers.SerializerMethodField()survey_item = serializers.IntegerField(source="pk")choices = ChoicesSerializer(source="answers", many=True, fields=("content", "points")) # fields: 指定要序列化的字段value = serializers.CharField(default="")error = serializers.CharField(default="")class Meta:model = models.SurveyItemfields = ("survey", # 問題所屬的調查問卷模板id"survey_item", # 問題的id"name", # 問題內容"answer_type", # 問題的類型"choices", # 如果是選擇題, 對應的選項"value", # 答案"error", # 用作于提示的錯誤信息 )def get_survey(self, instance):""":param instance::return:"""return self.context.get("survey_id")class SurveysSerializers(DynamicFieldsModelSerializer):"""2. 獲取調查問卷使用的問卷模板"""questions = serializers.ListSerializer(child=QuestionSerializer())class Meta:model = models.Surveyfields = ("id", # 問卷模板的id"name", # 問卷模板的名稱"questions", # 該問卷模板關聯的所有問題 )def to_representation(self, instance):""":param instance::return:"""self.context["survey_id"] = instance.pkdata = super(SurveysSerializers, self).to_representation(instance)return dataclass GetQuestionnaireDetailSerializers(DynamicFieldsModelSerializer):"""1. 獲取調查問卷詳情頁的序列化器的入口"""surveys = SurveysSerializers(many=True)class Meta:model = models.MiddleSurveyfields = ("name", # 調查表的名字"surveys", # 本次調查表使用的所有問題模板)
看著代碼挺多, 其實套路都是一樣
當要序列化的字段是一個外鍵關系時, 就給這個字段指定另外一個序列化器,?
如果是多對多, 那么序列化器中就需要指定many=True, 否則就不用.
和正常的使用序列化器一樣
上面說的是序列化, 還有反序列化, 同樣可以使用嵌套序列化器
?
轉載于:https://www.cnblogs.com/594504110python/p/10362674.html
總結
以上是生活随笔為你收集整理的djangorestframework怎么这么好用!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 护照要多少钱啊?
- 下一篇: 求电影:法国的女孩是一个奥地利的小公主,