我是Django/Django REST FW的新手(也是这个社区的新手)。我已经花了很多时间阅读文档,但在这一点上我还在原地打转。我提前为在这里如此冗长道歉。
我的后端数据库是Postgres。我有3个模型,User
,Item
和ShoppingList
。我需要Item
包含说明(item_name
字段)及其位置。用户将选择一个项目并将其添加到当天的ShoppingList
中。其想法是,用户在获得该项目后将其“勾选”,然后将其“删除”从X1 M6 N1 X的Angular 来看。
这就是我遇到麻烦的地方:我不想复制shopping_list
表中的item_name
和item_location
字段,但我需要在购物列表(shopping_lists.py
)的视图中显示这些字段。Item
和ShoppingList
之间分别存在一对多关系。Item
对象被视为存储每个物料的说明和位置的“主物料表”。ShoppingList
对象保存这些“主物料”的临时列表。我需要一个包含ShoppingList
中所有字段和Item
中2个或更多字段的查询集。
我认为这就是Django REST FW所认为的反向关系。我尝试了对序列化器和模型进行各种更改(包括将Item序列化器添加到ShoppingList序列化器),但得到了各种错误。
型号/item.py:
from django.db import models
from django.contrib.auth import get_user_model
class Item(models.Model):
item_name = models.CharField(max_length=50, db_index=True)
item_location = models.CharField(max_length=10, blank=True, db_index=True)
item_class = models.CharField(max_length=20, blank=True)
# This is a relationship with User model
shopper_id = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE
)
def __str__(self):
return f"item_name: {self.item_name}, item_location: {self.item_location}, shopper_id: {self.shopper_id}"
模特/购物清单.py:
from django.db import models
from django.contrib.auth import get_user_model
from .item import Item
class ShoppingList(models.Model):
item_num = models.ForeignKey(
'Item',
on_delete=models.DO_NOTHING # we don't want to delete the item from the "master" item list, just from this shopping list
)
# This is a relationship with user model.
shopper_id = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE # ...but we do want to delete the item if the user goes away as items are user-specific
)
item_qty = models.PositiveIntegerField()
item_complete = models.BooleanField(default=False)
added_on = models.DateField(auto_now=True)
# setting list_num to blank=True for this version
list_num = models.PositiveIntegerField(blank=True)
def __str__(self):
return f"item_num: {self.item_num}, shopper_id: {self.shopper_id}, item_qty: {self.item_qty}, item_complete: {self.item_complete}"
序列化程序/item.py:
from rest_framework import serializers
from ..models.item import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('id', 'item_name', 'item_location', 'item_class', 'shopper_id')
序列化器/购物清单.py:
from rest_framework import serializers
from ..models.shopping_list import ShoppingList
class ShoppingListSerializer(serializers.ModelSerializer):
class Meta:
model = ShoppingList
fields = ('id', 'item_num', 'shopper_id', 'item_qty', 'item_complete', 'added_on', 'list_num')
获取错误 * 属性错误:当我在下面的views/shopping_lists.py
中执行class ShoppingListItemView
中的GET方法时,无法通过ShoppingList示例 * 访问管理器:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from rest_framework.exceptions import PermissionDenied
from ..models.shopping_list import ShoppingList
from ..serializers.shopping_list import ShoppingListSerializer
from ..models.item import Item
from ..serializers.item import ItemSerializer
class ShoppingListsView(APIView):
def get(self, request, list_num):
shopping_items = ShoppingList.objects.filter(shopper_id=request.user.id)
shopping_list_items = shopping_items.filter(list_num=list_num)
data = ShoppingListSerializer(shopping_list_items, many=True).data
return Response(data)
def post(self, request):
request.data['shopper_id'] = request.user.id
list_item = ShoppingListSerializer(data=request.data, partial=True)
if list_item.is_valid():
list_item.save()
return Response(list_item.data, status=status.HTTP_201_CREATED)
else:
return Response(list_item.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, list_num):
shopping_items = ShoppingList.objects.filter(shopper_id=request.user.id)
shopping_list_items = shopping_items.filter(list_num=list_num)
response_data = shopping_list_items.delete()
return Response(response_data, status=status.HTTP_204_NO_CONTENT)
class ShoppingListsAllView(APIView):
def get(self, request):
shopping_items = ShoppingList.objects.filter(shopper_id=request.user.id)
data = ShoppingListSerializer(shopping_items, many=True).data
return Response(data)
class ShoppingListItemView(APIView):
def get(self, request, pk):
list_item = get_object_or_404(ShoppingList, pk=pk)
if request.user != list_item.shopper_id:
raise PermissionDenied('Unauthorized, this item belongs to another shopper')
else:
list_entry = list_item.objects.select_related('Item').get(id=pk)
print(list_entry)
data = ShoppingListSerializer(list_item).data
return Response(data)
def delete(self, request, pk):
list_item = get_object_or_404(ShoppingList, pk=pk)
if request.user != list_item.shopper_id:
raise PermissionDenied('Unauthorized, this item belongs to another shopper')
else:
list_item.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
def patch(self, request, pk):
list_item = get_object_or_404(ShoppingList, pk=pk)
if request.user != list_item.shopper_id:
raise PermissionDenied('Unauthorized, this item belongs to another shopper')
else:
request.data['shopper_id'] = request.user.id
updated_list_item = ShoppingListSerializer(list_item, data=request.data, partial=True)
if updated_list_item.is_valid():
updated_list_item.save()
return Response(updated_list_item.data)
else:
return Response(updated_item.errors, status=status.HTTP_400_BAD_REQUEST)
2条答案
按热度按时间2lpgd9681#
如果只想显示ShoppingList中某个项目的几个属性,则可以在序列化程序中使用SerializerMethodField方法
这将作为-
anyPropertyOfItem可以是项目模型中的任何内容。通过这种方式设置序列化程序,ShoppingList视图将自动显示2个新字段。
或者你也可以在模型中的@属性的帮助下定义只读字段来获得必需的字段。
如果你想在ShoppingList视图中显示商品的所有属性,你可以在这里写,将编辑我的答案。这里你需要使用related_name并获取ShoppingList序列化程序中的商品序列化程序作为额外的字段。
aiqt4smr2#
对于反向关系,应在定义模型或使用后缀_set时使用related_name。
related_name属性指定了用户模型到你的模型的反向关系的名称,如果你不指定related_name,Django会自动创建一个使用你的模型名加上后缀_set的反向关系
从What is related_name used for?复制到Wogan