I'm using Django REST framework. I've created a model for items in an inventory system and also a through table (named subassembly) for many-to-many relationship between items themselves, so an item can be a subpart of other items and vice versa.
I'm just not sure I've done it right and I can't seem to get any results. When I visit the backend at a URL such as http://localhost:8000/api/subassemblies/2/, the response is
{"detail": "Not found."}
but I'm hoping to see all of an item's subparts, or "children". PUT or any other type of request has the same outcome.
If it matters, when accessing the subassemblies from the admin page, I can create relationships between items just fine. But only one at a time though. And I need to be able to edit all of an item's subparts in one go (at least, frontend-wise). Currently, the request body is structured like so:
{
"parent_id": 2,
"children": [
{ "child_id": 5, "qty": 2 },
{ "child_id": 4, "qty": 3 },
]
}
This also allows me to use .set() on a particular item's children which is useful because I think it also removes any prior children that are not included in the new set.
views.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()
models.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)
serializers.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()
For referencing the parent and child item objects, I'm using a mixin or something from this post so I can do so with just their primary keys.
Also, the item serializer code currently has no reference to the subassembly through table or its serializer. I tried adding something like that but the error was still there and it also made the children field required when creating an item, which I don't want. That code looked like this:
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')
]
The other urls all work fine, it's just the subassemblies url that returns this error.