以下內容是我關於完成生鮮電商項目后的一點總結,可能只有做完這個項目的人可能勉強看得懂一點,當然更多是可能就只有我知道自己寫的什么鬼了....(笑)
這一點的感想主要是,在什么情況下重載CreateModelMixin里面的create()方法和perform_create()方法(這里只以CreateModelMixin舉例,其他例如RetrieveModelMixin等差不多),什么時候重載Serializer里面的create()方法,還有validate()的用法。
通過對這個項目中用到這種方法的總結,大概里面有8個地方用到了上面所說的方法。
一、首先是validate()的用法,出現的地方有:
①用戶注冊時,在通過前面各種驗證之后,使用“ attrs["mobile"] = attrs["username"] ”,創建一個鍵值對,把前端傳過來的手機號碼保存起來,這里的"mobile"是與用戶表中的字段保持一致。然后用“ del attrs["code"] ”刪除驗證碼。
def validate(self, attrs): # 前端沒有傳mobile值到后端,這里添加進來 attrs["mobile"] = attrs["username"] # code是自己添加得,數據庫中並沒有這個字段,驗證完就刪除掉 del attrs["code"] return attrs
對這段的分析,就是用戶在前端傳過來三個數據(username,password,code),然后在CreateModelMixin里面把這些數據交給我們自定義的serializer進行驗證,驗證成功后,本來下一步就是調用perform_create()進行保存,可是因為我們設計的表中有mobile字段,且沒有code字段,所以就在前一步,也就是驗證成功后到調用perform_create()之前,添加mobile字段,刪除多余的code字段。
②在訂單管理接口時,在validate()中添加自動生成的訂單號。
def validate(self, attrs): # validate中添加order_sn,然后在view中就可以save attrs["order_sn"] = self.generate_order_sn() return attrs
綜上所述,可以知道,validate()的一個作用,就是提交上來的數據驗證成功后,在保存到數據庫之前,根據設計的表的需要對要進行保存的數據進行其他必要的操作。(增刪等)
二、接下來介紹重載Serializer的create()方法的情況。
①對密碼進行加密保存。Serialzier的create()本來就是數據驗證(is_valid)通過后,CreateModelMixin調用perform_create(),然后里面的.save()方法調用Serializer的create()方法把數據自動保存到數據庫中(當然,這里的前提是繼承ModelSerializer)。重載Serializer的create(),意味着要我們自己去寫保存數據的邏輯,不過項目中用了另一種做法避免了自己寫保存邏輯。
# 密碼加密保存 def create(self, validated_data): user = super(UserRegSerializer, self).create(validated_data=validated_data) user.set_password(validated_data["password"]) user.save() return user
②添加商品到購物車時,由於繼承是Serializer而不是ModelSerializer,所以需要重載create()
def create(self, validated_data): user = self.context["request"].user nums = validated_data["nums"] goods = validated_data["goods"] existed = ShoppingCart.objects.filter(user=user, goods=goods) if existed: existed = existed[0] existed.nums += nums existed.save() else: existed = ShoppingCart.objects.create(**validated_data)
綜上所述,重載Serializer的情況有:①繼承Serializer的時候需要我們重載;②繼承ModelSerializer的時候,如果對保存到數據庫的數據需要進行額外的操作,可以重載Serializer的create()。
三、介紹重載CreateModelMixin的create()(或者說成ModelViewset's create())的情況。
①把用戶生成的token加載到頭部header中時,重載CreateModelMixin的create()。這樣才可以用到里面的添加信息到header的操作。
def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = self.perform_create(serializer) re_dict = serializer.data payload = jwt_payload_handler(user) re_dict["token"] = jwt_encode_handler(payload) re_dict["name"] = user.name if user.name else user.username headers = self.get_success_headers(serializer.data) return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
綜上所述,如果要把信息添加到header里面,就重載CreateModelMixin的create()方法。
四、重載perform_create()方法。
①創建訂單后,重載perform_create(),實例化"order = serializer.save()",把購物車的商品和訂單order一起添加到訂單的商品詳情表中。
def perform_create(self, serializer): order = serializer.save() shop_carts = ShoppingCart.objects.filter(user=self.request.user) for shop_cart in shop_carts: order_goods = OrderGoods() order_goods.goods = shop_cart.goods order_goods.goods_num = shop_cart.nums order_goods.order = order order_goods.save() # 清空購物車 shop_cart.delete() return order
②用戶添加收藏,實例化收藏記錄"instance = serializer.save()",然后通過“goods = instance.goods”獲取到商品,對它的goods.fav_nums += 1。
def perform_create(self, serializer): instance = serializer.save() goods = instance.goods goods.fav_num += 1 goods.save()
綜上所述,重載perform_create()的情況有,如果需要利用到保存后的數據,例如購物車的商品以及數量,來減去庫存里的,這里就可以重寫perfrom_create方法來接收剛剛保存的記錄,提取里面的值進行額外操作。
