寫在前面
在使用Django-rest-framework提交併創建數據時,有時候服務器端需要對傳過的來的數據進行處理並重新賦值後再創建到數據庫。
例:
在我的models.py裏面有兩個表級聯
# models.py
class User(models.Model):
u_name = models.CharField(max_length=32, unique=True)
class Addr(models.Model):
a_user = models.ForeignKey(User, on_delete=models.CASCADE)
a_order_id = models.IntegerField(default=0)
這時我要給用戶添加一個新的地址。但是a_user字段不能讓用戶填寫,而是後臺通過查詢User表後傳過去,然後創建新的地址
# Serializer.py
class AddrSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Addr
fields = ('a_order_id', 'a_user')
1、思路
當我們不需要改變修改PORT提交的數據時
class AddrAPIView(ListCreateAPIView):
serializer_class = AddrSerializer
queryset = Addr.objects.all()
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
當我們需要改變修改PORT提交的數據時
# views.py
class AddrAPIView(ListCreateAPIView):
serializer_class = AddrSerializer
queryset = Addr.objects.all()
def post(self, request, *args, **kwargs):
data = QueryDict(request.data.urlencode(), mutable=True)
data.update({'a_user': 'http://127.0.0.1:8000/static/user/1/'})
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return Response(serializer.data)
思路:
-
post方法裏寫入數據的是return self.create(request, *args, **kwargs)
-
我們通過查看create()源碼發現,傳遞request數據的是:
serializer = self.get_serializer(data=request.data),
而這個request.data是QueryDict類型的(不能直接修改數據) -
request.data.urlencode()打印出來的是QueryDict()類型可以接收的源數據
-
‘a_user’ 字段在序列化serializer裏面寫了,網頁裏面可以不提交這個數據。但是在serializer裏面不寫這個字段,創建時會導致報錯
2、更簡單點
上面是利用Django-rest-framework裏面的序列化工具創建的,其實這樣改來改去反倒變得複雜了,當然如果前端需要這樣的API返回還是很有必要的,其實可以直接創建addr = Addr(),然後手動戳你需要修改的數據,保存就可以了
class AddrAPIView(ListCreateAPIView):
serializer_class = AddrSerializer
queryset = Addr.objects.all()
def post(self, request, *args, **kwargs):
addr = Addr()
addr.a_user = User.objects.get(pk=u_id)
addr.a_order_id = request.data["a_order_id"]
addr.save()
return Response({"status": 901})