I chose the Django REST Framework and drf-nested-routers to create an API for products and ProductReports. Here are the relevant classes:
# models.py from django.db import models class Product(models.Model): created_at = models.DateTimeField(auto_now_add=True) class ProductReport(models.Model): user_name = models.CharField(max_length=256, blank=False) created_at = models.DateTimeField(auto_now_add=True) product = models.ForeignKey('Product', default=1)
...
...
# views.py from django.shortcuts import render from rest_framework import viewsets, mixins from rest_framework.response import Response from models import Product, ProductReport from serializers import ProductSerializer, ProductReportSerializer class ProductViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer class ProductReportViewSet(viewsets.ViewSet): queryset = ProductReport.objects.all() serializer_class = ProductReportSerializer def list(self, request, product_pk=None): queryset = self.queryset.filter(product=product_pk) serializer = ProductReportSerializer(queryset, many=True, context={'request': request}) return Response(serializer.data) def retrieve(self, request, pk=None, product_pk=None): queryset = self.queryset.get(pk=pk, product=product_pk) serializer = ProductReportSerializer(queryset) return Response(serializer.data)
...
# urls.py from django.conf.urls import patterns, include, url from django.contrib import admin from rest_framework import routers from rest_framework_nested.routers import SimpleRouter, NestedSimpleRouter from productreports import views router = routers.SimpleRouter() router.register(r'products', views.ProductViewSet) products_router = NestedSimpleRouter(router, r'products', lookup='product') products_router.register(r'productreports', views.ProductReportViewSet) urlpatterns = patterns('', url(r'^', include(router.urls)), url(r'^', include(products_router.urls)), url(r'^admin/', include(admin.site.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), )
When visiting http://localhost:8000/products/1/productreports/ , the following error is displayed:
Incorrectly configured in / products / 1 / productreports /
Unable to resolve URLs for hyperlinks using view name "productreport-detail". You may not have been able to include the linked model in your API, or you might have incorrectly configured the lookup_field attribute in this field.
There are a few things that I'm not sure about whether they are configured correctly:
product = models.ForeignKey('Product', default=1)many=True in serializer = ProductReportSerializer(queryset, many=True, context={'request': request}) ... each product can have many product reportsProductReportSerializer in generallookup='product' in products_router = NestedSimpleRouter(router, r'products', lookup='product')
Update
I noticed that an error only occurs when there is at least one product associated with it for a product. . If the productreports table does not contain an entry for a specific product, then the API response is excellent.
When I check the serializer in ProductReportViewSet#list , I get:
ProductReportSerializer([ <ProductReport: ProductReport object>, <ProductReport: ProductReport object>, <ProductReport: ProductReport object>, <ProductReport: ProductReport object>, <ProductReport: ProductReport object>, <ProductReport: ProductReport object>, '...(remaining elements truncated)...'], context={'request': <rest_framework.request.Request object>}, many=True): url = HyperlinkedIdentityField(view_name='productreport-detail') product = ProductSerializer(): url = HyperlinkedIdentityField(view_name='product-detail') created_at = DateTimeField(read_only=True) user_name = CharField(max_length=256) created_at = DateTimeField(read_only=True)