12👍
Here is another way I’ve done this:
views.py
from models import Customer, Order
from serializers import CustomerSerializer, OrderSerializer
from rest_framework import generics
class CustomerList(generics.ListCreateAPIView):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
class CustomerDetail(generics.RetrieveUpdateDestroyAPIView)
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
class OrdersByCustomer(generics.ListCreateAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
def get_queryset(self):
customer_pk = self.kwargs['customer_pk']
return self.queryset.filter(customer__pk=customer_pk)
def pre_save(self, obj):
obj.customer_id = self.kwargs['customer_pk']
class OrderDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
serializers.py
from models import Customer, Order
from rest_framework import serializers
from rest_framework.reverse import reverse
class OrderSerializer(serializers.HyperlinkedModelSerializer)
class Meta:
model = Order
class CustomerSerializer(serializers.HyperlinkedModelSerializer)
orders = serializers.SerializerMethodField('get_customer_orders')
def get_customer_orders(self, obj):
return reverse('ordersbycustomer-list',
args=[obj.pk], request=self.context['request'])
class Meta:
model = Customer
urls.py
from django.conf.urls import patterns, include, url
from views import OrdersByCustomer, CustomerDetail, CustomerList
urlpatterns = patterns("",
url(r'^customers/(?P<customer_pk>.+)/orders/$', OrdersByCustomer.as_view(), name='ordersbycustomer-list'),
url(r'^customers/(?P<pk>.+)/$', CustomerDetail.as_view(), name='customer-detail'),
url(r'^customers/$', CustomerList.as_view(), name='customer-list'),
)
There is more code involved than with Viewsets/Routers but this gives you much more control over what is going on.
Here I have chosen to only expose orders as children of a customer. Since they are separated, you can use different serializer classes for list vs detail.
8👍
Here is how I have achieved this using the new ViewSets and Routers from Rest-Framework version 2.3:
views.py:
from rest_framework import viewsets
from rest_framework.response import Response
from models import Order, OrderLine
from serializers import OrderSerializer, OrderLineSerializer
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
@link()
def lines(self, request, pk=None):
queryset = OrderLine.objects.filter(order__pk=pk)
serializer = OrderLineSerializer(queryset,
context={'request':request},
many=True)
return Response(serializer.data)
class OrderLineViewSet(viewsets.ModelViewSet):
queryset = OrderLine.objects.all()
serializer_class = OrderLineSerializer
serializers.py
from rest_framework import serializers
from models import Order, OrderLine
class OrderSerializer(serializers.HyperlinkedModelSerializer):
lines = serializers.HyperlinkedIdentityField(view_name='order-lines')
class Meta:
model = Order
class OrderLineSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = OrderLine
urls.py
from views import OrderViewSet, OrderLineViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'order', OrderViewSet)
router.register(r'orderline', OrderLineViewSet)
urlpatterns = router.urls
Now ‘order/id/lines’ will return a list of serialized Order Lines that have a relationship with the Order identified by that id.
Any method on a ViewSet decorated with @link or @action will be given a URL when you register the view with the router.
- [Django]-Get the latest record with filter in Django
- [Django]-How can I store an array of strings in a Django model?
- [Django]-Django URLS, how to map root to app?
1👍
I added def get_queryset(self): issue_id = self.kwargs[‘issue_id’] return Page.objects.filter(issue_id = issue_id) to PageList and now GET works for issue/
/pages. Now I just have to figure out how to post as well.I added def pre_save(self, obj): obj.issue_id = self.kwargs[‘issue_id’] to PageList and now POST works too. Querying pages from an issue that doesn’t exist returns an empty result rather than 404 not found though. If anyone knows of a better way to do this I’m very interested to hear about it.
If your method get_queryset(self) returns an empty list instead of 404 NOT FOUND, I would suggest to use the shortcut function get_list_or_404 from django.
The method could look like this:
from django.shortcuts import get_list_or_404
def get_queryset(self):
filter = {}
filter['issue_id'] = self.kwargs['issue_id']
return get_list_or_404(self.queryset, **filter)
I know this is an old post, but maybe this could help other people having the same or some similar problem.
- [Django]-How to resolve AssertionError: .accepted_renderer not set on Response in django and ajax
- [Django]-How to access array elements in a Django template?
- [Django]-Running fabric script locally