姜戈 REST 框架 |多对多关系返回"detail: not found"



我使用的是Django REST框架。我为库存系统中的项目创建了一个模型,也为项目本身之间的多对多关系创建了贯穿表(命名为子组件(,因此一个项目可以是其他项目的子部分,反之亦然。

我只是不确定我做得对,而且我似乎没有得到任何结果。当我访问诸如http://localhost:8000/api/subassemblies/2/,响应为

{"detail": "Not found."}

但我希望看到一个项目的所有子部分,或者";儿童";。PUT或任何其他类型的请求都具有相同的结果。

如果重要的话,当从管理页面访问子组件时,我可以很好地创建项目之间的关系。但一次只能有一个。我需要能够一次性编辑项目的所有子部分(至少在前端(。目前,请求主体的结构如下:

{   
"parent_id": 2,
"children": [
{ "child_id": 5, "qty": 2 },
{ "child_id": 4, "qty": 3 },
]
}

这也允许我在特定项的子项上使用.set((,这很有用,因为我认为它还可以删除任何未包含在新集合中的先前子项。

视图.py

class SubassemblyDetail(generics.RetrieveUpdateDestroyAPIView):
"""
Retrieve, update, or delete a particular items subassembly
"""
queryset = Subassembly.objects.all()
serializer_class = SubassemblySerializer
def get_queryset(self):
item_id = self.kwargs['pk']
item = Item.objects.get(pk=item_id)
return item.children.all()

型号.py

class Item(models.Model):
# ... (various other fields)
children = models.ManyToManyField('self', through='Subassembly', blank=True)
class Subassembly(models.Model):
parent_id = models.ForeignKey(Item, related_name='parent_item', on_delete=models.CASCADE)
child_id = models.ForeignKey(Item, related_name='child_item', on_delete=models.CASCADE)
child_qty = models.PositiveSmallIntegerField(default=1)

序列化程序.py

class SubassemblySerializer(ModelSerializer):
parent_id = get_primary_key_related_model(ShortItemSerializer)
child_id = get_primary_key_related_model(ShortItemSerializer)
class Meta:
model = Subassembly
fields = '__all__'
def update(self, instance, validated_data):
children = validated_data.pop('children')
child_list = []
qty_list = []
for child in children:
pk = child['child_id']
qty = child['qty']
obj = Item.objects.get(id=pk)
child_list.append(obj)
qty_list.append(qty)
instance.children.set(child_list, through_defaults={'qty': qty_list})
instance.save()
return instance
def delete(self, instance):
instance.children.clear()

为了引用父项和子项对象,我使用了本文中的mixin或其他东西,这样我就可以只使用它们的主键。

此外,项目序列化程序代码当前没有通过表或其序列化程序引用部件。我尝试添加类似的内容,但错误仍然存在,而且在创建项目时还需要children字段,这是我不想要的。代码看起来是这样的:

class ItemSerializer(ModelSerializer):
# ... (other fields)
children = SubassemblySerializer(many=true)    
def create(self, validated_data):
return Item.objects.create(**validated_data)
class Meta:
model = Item
fields = '__all__'

urls.py

urlpatterns = [
path('', views.RouteList.as_view()),
path('items/', views.ItemList.as_view(), name='item-list'),
path('items/<int:pk>/', views.ItemDetail.as_view(), name='item-detail'),
path('suppliers/', views.SupplierList.as_view(), name='supplier-list'),
path('suppliers/<int:pk>/', views.SupplierDetail.as_view(), name='supplier-detail'),
path('subassemblies/<int:pk>/', views.SubassemblyDetail.as_view(), name='subassembly-detail')
]

其他url都工作正常,只是组件url返回了这个错误。

如果我理解正确,您的问题涉及从Item对象检索children。我怀疑Item对象没有被检索到。诊断方法如下:

使用以下命令进入Django交互式shell:

python manage.py shell

在外壳内执行以下操作:

# Import Item    
from <your_model_name>.models import Item
# Retrieve an Item object
item = Item.objects.get(id=2)
# Retrieve children
children = item.children.all()
# Get the count of children
print(children.count())

如果children.count()为0,则表示您的项目对象没有任何子对象。如果你能排除这种可能性,那就意味着你的视图或序列化程序就是问题所在。

粗略地看,SubAssemblyDetail中的get_queryset()方法返回一个Item查询集,这可能是一个问题。在引擎盖下,SubAssemblyDetail执行retrieve()方法,请参阅:https://www.cdrf.co/3.13/rest_framework.generics/RetrieveUpdateDestroyAPIView.html

已解决!多亏了Hamster Hooey,问题是在SubassemblyDetail视图下的get_queryset()方法中,我返回的是项查询集,而不是子组件查询集,这似乎是Django无法接受的。

所以我没有做item.children.all(),而是做了Subassembly.objects.filter(parent_id=item_id),结果一切都很好。

相关内容

最新更新