![](/img/trans.png)
[英]Include intermediary (through model) in responses in Django Rest Framework
[英]How do I include intermediary Models in my Django Rest Framework API
目前,我正在學習有關Django Rest Framework的知識,偶然發現了一個棘手的部分,我似乎無法在我們的項目中工作。 我們的項目是一個虛構的網上商店,您可以在其中將愛犬嬰兒放入購物車並訂購。 我們的前端通過Django Rest Framework與后端進行通信。 我們擁有的三個主要模型是“用戶”,“訂單”和“小狗”。 因為每個訂單都有一個幼犬列表,每個幼犬都有自己的數量,所以我們需要兩者的中介模型,因為簡單的ManyToManyField顯然無法處理額外的列。 這使事情變得更加復雜(至少對於Django新手而言)。
如何在序列化器和視圖中反映關系,如何形成從前端發送的JSON對象?
也:
在哪里可以計算訂單總價?
即使我不想編輯或獲得一個特定的訂單,我也需要OrderDetail視圖嗎?或者OrderList視圖足夠嗎?
這里有一個問題正在解決類似的問題: 在Django Rest Framework的響應中包括中介(通過模型),我在代碼中實現了它,並使它現在可以工作,這要感謝Daniel Roseman的評論。 現在可以通過/ admin手動創建訂單並獲取訂單。 我仍然無法通過API創建訂單。
這是我的代碼:
models.py:
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Puppy(models.Model):
name = models.CharField(max_length=30)
price = models.DecimalField(max_digits=6, decimal_places=2)
image_url = models.CharField(max_length=200)
age = models.IntegerField(null=True)
weight = models.IntegerField(null=True)
description_de = models.CharField(max_length=500, null=True)
description_en = models.CharField(max_length=500, null=True)
def __str__(self):
return self.name
class Order(models.Model):
total_price = models.DecimalField(max_digits=9, decimal_places=2)
puppies = models.ManyToManyField(Puppy, through='PuppyOrder')
date = models.DateTimeField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='orders')
def save(self, *args, **kwargs):
"""
Create a new Order
"""
print("An order is being saved: " + str(Order.id))
super(Order, self).save(*args, **kwargs)
def __str__(self):
return str(self.id)
class PuppyOrder(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
puppy = models.ForeignKey(Puppy, on_delete=models.CASCADE)
amount = models.IntegerField()
def __str__(self):
return self.id
class Address(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# Some more address fields ...
@receiver(post_save, sender=User)
def create_user_address(sender, instance, created, **kwargs):
if created:
Address.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_address(sender, instance, **kwargs):
instance.address.save()
views.py:
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.serializers import VerifyJSONWebTokenSerializer
from .serializers import UserSerializer, UserSerializerWithToken, OrderSerializer, PuppySerializer
from .permissions import IsOwner
@api_view(['GET'])
def api_root(request, format=None):
return Response({
'users': reverse('user-list', request=request, format=format),
'orders': reverse('order-list', request=request, format=format),
'puppies': reverse('puppy-list', request=request, format=format),
})
class OrderList(generics.ListCreateAPIView):
http_method_names = ["get", "post"]
queryset = Order.objects.all()
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
serializer_class = OrderSerializer
def get_queryset(self):
# Validation Code and getting self.request.user from jwt token ...
if self.request.user.is_anonymous:
return None
return Order.objects.all().filter(user=self.request.user)
def perform_create(self, serializer):
# Validation Code and getting self.request.user from jwt token ...
serializer.save(user=self.request.user)
class OrderDetail(generics.RetrieveUpdateDestroyAPIView):
http_method_names = ["get", "post"]
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
queryset = Order.objects.all()
serializer_class = OrderSerializer
class UserList(generics.ListAPIView):
http_method_names = ["get", "post"]
queryset = User.objects.all().select_related('address')
serializer_class = UserSerializer
class UserDetail(generics.RetrieveAPIView):
http_method_names = ["get", "post"]
queryset = User.objects.all().select_related('address')
serializer_class = UserSerializer
class PuppyList(generics.ListAPIView):
http_method_names = ["get"]
permission_classes = (permissions.AllowAny,)
queryset = Puppy.objects.all()
serializer_class = PuppySerializer
class PuppyDetail(generics.RetrieveAPIView):
http_method_names = ["get"]
permission_classes = (permissions.AllowAny,)
queryset = Puppy.objects.all()
serializer_class = PuppySerializer
serializers.py:
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings
from django.contrib.auth.models import User
from .models import Order, Puppy, PuppyOrder
class UserSerializer(serializers.ModelSerializer):
orders = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'orders')
class UserSerializerWithToken(serializers.ModelSerializer):
# Neccessary code for generating a JWT token ...
class PuppySerializer(serializers.ModelSerializer):
description = serializers.SerializerMethodField()
def get_description(self, puppy):
return {'DE': puppy.description_de, 'EN': puppy.description_en}
class Meta:
model = Puppy
fields = ('id', 'name', 'price', 'image_url', 'age', 'weight', 'description')
class PuppyOrderSerializer(serializers.ModelSerializer):
puppy = serializers.ReadOnlyField(source='order.puppy')
order = serializers.ReadOnlyField(source='order.order')
class Meta:
model = PuppyOrder
fields = ('id', 'puppy', 'amount')
class OrderSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
puppies = PuppyOrderSerializer(source='puppyorder_set', many=True)
# This is currently producing an error
# puppies = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Order
fields = ('id', 'total_price', 'puppies', 'date', 'user')
隨時告訴我,您是否在我的代碼中看到某些可以改進或沒有意義的東西。 在此先感謝您,任何幫助將不勝感激!
通過在PuppyOrder模型中的ForeignKeys上指定related_names,您已經破壞了事情。 刪除那些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.