整體單改路由層、模型層、序列化層不需要做修改,只需要處理視圖層:views.py """ 1) 單整體改,說(shuō)明前臺(tái)要提供修改的數(shù)據(jù),那么數(shù)據(jù)就需要校驗(yàn),校驗(yàn)的數(shù)據(jù)應(yīng)該在實(shí)例化“序列化類對(duì)象”時(shí),賦值給data 2)修改,就必須明確被修改的模型類對(duì)象,并在實(shí)例化“序列化類對(duì)象”時(shí),賦值給instance 3)整體修改,所有校驗(yàn)規(guī)則有required=True的字段,都必須提供,因?yàn)樵趯?shí)例化“序列化類對(duì)象”時(shí),參數(shù)partial默認(rèn)為False 注:如果partial值設(shè)置為True,就是可以局部改 1)單整體修改,一般用put請(qǐng)求: V2BookModelSerializer( instance=要被更新的對(duì)象, data=用來(lái)更新的數(shù)據(jù), partial=默認(rèn)False,必須的字段全部參與校驗(yàn) ) 2)單局部修改,一般用patch請(qǐng)求: V2BookModelSerializer( instance=要被更新的對(duì)象, data=用來(lái)更新的數(shù)據(jù), partial=設(shè)置True,必須的字段都變?yōu)檫x填字段 ) 注:partial設(shè)置True的本質(zhì)就是使字段 required=True 校驗(yàn)規(guī)則失效 """ class V2Book(APIView): # 單整體改: 對(duì) v2/books/(pk)/ 傳的數(shù)據(jù)是與model對(duì)應(yīng)的字典{name|price|publish|authors} def put(self, request, *args, **kwargs): request_data = request.data pk = kwargs.get('pk') old_book_obj = models.Book.objects.filter(pk=pk).first() # 通過(guò)源碼我們知道instance不為none的時(shí)候才會(huì)走save()中的update,若依我們要拿到這個(gè)要更新數(shù)據(jù)的對(duì)象,把它賦給instanc # 目的:將眾多數(shù)據(jù)的校驗(yàn)交給序列化類來(lái)處理 - 讓序列化類扮演反序列化角色,校驗(yàn)成功后,序列化類來(lái)幫你入庫(kù) book_ser = serializers.V2BookModelSerializer(instance=old_book_obj, data=request_data, partial=False) book_ser.is_valid(raise_exception=True) # 校驗(yàn)通過(guò),完成數(shù)據(jù)的更新:要更新的目標(biāo),用來(lái)更新的新數(shù)據(jù) book_obj = book_ser.save() return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.V2BookModelSerializer(book_obj).data }) 單與整體局部修改序列化層:serializers.py# 重點(diǎn):ListSerializer與ModelSerializer建立關(guān)聯(lián)的是: # ModelSerializer的Meta類的 - list_serializer_class class V2BookListSerializer(ListSerializer): def update(self, instance, validated_data): # print(instance) # 要更新的對(duì)象們 # print(validated_data) # 更新的對(duì)象對(duì)應(yīng)的數(shù)據(jù)們 # print(self.child) # 服務(wù)的模型序列化類 - V2BookModelSerializer for index, obj in enumerate(instance): self.child.update(obj, validated_data[index]) return instance # 原模型序列化類變化 class V2BookModelSerializer(ModelSerializer): class Meta: # ... # 群改,需要設(shè)置 自定義ListSerializer,重寫群改的 update 方法 list_serializer_class = V2BookListSerializer # ... 視圖層:views.pyclass V2Book(APIView): # 單局部改:對(duì) v2/books/(pk)/ 傳的數(shù)據(jù),數(shù)據(jù)字段key都是選填 # 群局部改:對(duì) v2/books/ # 請(qǐng)求數(shù)據(jù) - [{pk:1, name:123}, {pk:3, price:7}, {pk:7, publish:2}] def patch(self, request, *args, **kwargs): request_data = request.data pk = kwargs.get('pk') # 將單改,群改的數(shù)據(jù)都格式化成 pks=[要需要的對(duì)象主鍵標(biāo)識(shí)] | request_data=[每個(gè)要修改的對(duì)象對(duì)應(yīng)的修改數(shù)據(jù)] if pk and isinstance(request_data, dict): # 單改 pks = [pk, ] request_data = [request_data, ] elif not pk and isinstance(request_data, list): # 群改 pks = [] for dic in request_data: # 遍歷前臺(tái)數(shù)據(jù)[{pk:1, name:123}, {pk:3, price:7}, {pk:7, publish:2}],拿一個(gè)個(gè)字典 #從拿出來(lái)的一個(gè)個(gè)字段中彈出pk的值,如果沒有就返回None pk = dic.pop('pk', None) # 下面的作用是將pk的值添加到pks中,如果為None的話,直接返回異常,所以能走下的pks和request_data中的數(shù)據(jù)是一一對(duì)應(yīng)的 if pk: pks.append(pk) else: return Response({ 'status': 1, 'msg': '數(shù)據(jù)有誤', }) else: return Response({ 'status': 1, 'msg': '數(shù)據(jù)有誤', }) # pks與request_data數(shù)據(jù)篩選, # 1)將pks中的沒有對(duì)應(yīng)數(shù)據(jù)的pk與數(shù)據(jù)已刪除的pk移除,request_data對(duì)應(yīng)索引位上的數(shù)據(jù)也移除 # 2)將合理的pks轉(zhuǎn)換為 objs objs = [] new_request_data = [] for index, pk in enumerate(pks): try: # pk對(duì)應(yīng)的數(shù)據(jù)合理,將合理的對(duì)象存儲(chǔ) obj = models.Book.objects.get(pk=pk) objs.append(obj) # 對(duì)應(yīng)索引的數(shù)據(jù)就需要保存下來(lái) new_request_data.append(request_data[index]) except: # 重點(diǎn):反面教程 - pk對(duì)應(yīng)的數(shù)據(jù)有誤,將對(duì)應(yīng)索引的data中request_data中移除 # index = pks.index(pk) # request_data.pop(index) continue book_ser = serializers.V2BookModelSerializer(instance=objs, data=new_request_data, partial=True, many=True) book_ser.is_valid(raise_exception=True) book_objs = book_ser.save() return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.V2BookModelSerializer(book_objs, many=True).data }) 總結(jié)""" 整體修改和局部修改的區(qū)別:partial=True,使字段變成可選字段,也就是不用全都輸入一遍 單整體改時(shí)要注意為了走save()中的update也給instance傳對(duì)象 單整體和單局部要把pk和request_data變成數(shù)組,并對(duì)數(shù)據(jù)進(jìn)行篩選,然后將pk對(duì)應(yīng)的對(duì)象取出放在一個(gè)數(shù)組里,循環(huán)用pk從數(shù)據(jù)庫(kù)中拿出對(duì)應(yīng)的對(duì)象放入一個(gè)對(duì)象數(shù)組中(如果出現(xiàn)了數(shù)據(jù)中沒有的PK會(huì)報(bào)錯(cuò)),將pk對(duì)應(yīng)的request_data的數(shù)據(jù)放入新的數(shù)組,將對(duì)象數(shù)組和新的request_data數(shù)組進(jìn)行反序列化并保存(注意many=True) """ ? 來(lái)源:https://www./content-4-511351.html |
|