Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save davemerwin/bad642979b9681d3b0e8 to your computer and use it in GitHub Desktop.
Save davemerwin/bad642979b9681d3b0e8 to your computer and use it in GitHub Desktop.
This is a (mostly) complete relationship example of a parent child relationship via Django Rest Framework
# This example will allow you to manipluate a Parent and a Child via various endpoints
# /api - All endpoints
# /api/parents - Parents list
# /api/parents/(?P<pk>\d+) - Parent detail
# /api/parents/(?P<pk>\d+)/children - List of children of parent
# /api/children - Child list
# /api/children/(?P<pk>\d+) - Child Detail
# Models - models.py
# Pretty simple setup. Children have a FK to parent
from django.db import models
from django.contrib.auth.models import User
class Parent(models.Model):
user = models.ForeignKey(User, related_name="user_parent")
# other fields
class Meta:
verbose_name = 'Parent'
verbose_name_plural = 'Parents'
class Child(models.Model):
user = models.ForeignKey(User, related_name="user_child")
parent = models.ForeignKey(Parent, related_name="parent_child")
# other fields
class Meta:
verbose_name = 'Child'
verbose_name_plural = 'Children'
# Permisions - permissions.py
# Basic permisions
from rest_framework.permissions import BasePermission, SAFE_METHODS
class IsStaffOrOwner(BasePermission):
def has_permission(self, request, view):
# allow user to list all users if logged in user is staff
return view.action == 'retrieve' or 'create' or request.user.is_staff
def has_object_permission(self, request, view, obj):
return request.user.is_staff or request.user == obj.user
# Serializers - serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
from myproject.myapp import models
class ChildSerializer(serializers.HyperlinkedModelSerializer):
user_child = serializers.HyperlinkedRelatedField(view_name="user-detail", read_only=True)
class Meta:
model = models.Child
fields = ('id', 'url', 'user',)
class ParentSerializer(serializers.HyperlinkedModelSerializer):
parent_child = serializers.HyperlinkedRelatedField(many=True, required=False, view_name='child-detail')
user_parent = serializers.HyperlinkedRelatedField(view_name="user-detail", read_only=True)
class Meta:
model = models.Parent
fields = ('id', 'url', 'user', 'parent_child')
# API Views - views.py
from django.contrib.auth.models import User
from rest_framework import viewsets
from rest_framework.decorators import list_route, detail_route
from rest_framework.response import Response
from .serializers import ParentSerializer, ChildSerializer
from .permissions import IsStaffOrOwner
from myproject.myapp import models
class ChildViewSet(viewsets.ModelViewSet):
serializer_class = ChildSerializer
permission_classes = (IsStaffOrOwner,)
def get_queryset(self):
if self.request.user.is_superuser:
return models.Child.objects.all()
else:
return self.request.user.user_child.all()
def pre_save(self, obj):
obj.user = self.request.user
class ParentViewSet(viewsets.ModelViewSet):
serializer_class = ParentSerializer
permission_classes = (IsStaffOrOwner,)
def get_queryset(self):
if self.request.user.is_superuser:
return models.Parent.objects.all()
else:
return self.request.user.user_parent.all()
def pre_save(self, obj):
obj.user = self.request.user
# The detail_route allows me to see all the children of a parent
# with the following URL: /api/parents/(?P<pk>\d+)/children
@detail_route()
def children(self, request, pk):
parent = self.get_object(pk)
children = parent.parent_child.all()
serializer = ChildSerializer(hints)
return Response(serializer.data)
# API URLS - urls.py
from django.conf.urls import patterns, include, url
from rest_framework.routers import DefaultRouter
from .myapp.api import views as myapp_views
router = DefaultRouter(trailing_slash=False)
router.register(r'children', myapp_views.ChildViewSet, base_name="child")
router.register(r'parent', myapp_views.TaskViewSet, base_name="parent")
urlpatterns = patterns('',
# API URIs
url(r'^api/', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
)
@code-shoily
Copy link

What's with the "hints" in line 111 ? I am just browsing your code and shouldn't it throw a NameError? Thanks for boiling it down to a nearly complete piece dude! Good stuff :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment