Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django-rest-framework nested urls with drf-nested-routers

I am building nested API with drf-nested-routers package.

However /domains/1/nameservers/ gives me all nameservers I have, not only one related to domain#1

I think the problem is that I use default tutorial NameServerViewSet implementation

class NameserverViewSet(viewsets.ModelViewSet):
    queryset = Nameserver.objects.all()
    serializer_class = NameserverSerializer

Please help me code it right way.

Below are examples from drf-nested-routers github page.

drf-nested-routers provides nested router that generates url patterns below

\domain\ <- Domains list \domain{pk}\ <- One domain, from {pk]

\domain{domain_pk}\nameservers\ <- Nameservers of domain from

{domain_pk} \domain{domain_pk}\nameservers\ {pk}\ <- Specific nameserver from {pk}, of domain from {domain_pk}

Here is an example:

# urls.py
from rest_framework_nested import routers
from views import DomainViewSet, NameserverViewSet
(...)

router = routers.SimpleRouter()
router.register(r'domains', DomainViewSet)

domains_router = routers.NestedSimpleRouter(router, r'domains', lookup='domain')
domains_router.register(r'nameservers', NameserverViewSet)

urlpatterns = patterns('',
    url(r'^', include(router.urls)),
    url(r'^', include(domains_router.urls)),
)
like image 957
Artem Fedosov Avatar asked Mar 05 '14 10:03

Artem Fedosov


People also ask

How do you use a router in DRF?

Routers are used with ViewSets in django rest framework to auto config the urls. Routers provides a simple, quick and consistent way of wiring ViewSet logic to a set of URLs. Router automatically maps the incoming request to proper viewset action based on the request method type(i.e GET, POST, etc).

What is Basename in router Django?

basename - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the queryset attribute of the viewset, if it has one. Note that if the viewset does not include a queryset attribute then you must set basename when registering the viewset.

What is Viewset in Django REST framework?

Django REST framework allows you to combine the logic for a set of related views in a single class, called a ViewSet . In other frameworks you may also find conceptually similar implementations named something like 'Resources' or 'Controllers'.

What is Django REST framework browsable API?

The browsable API feature in the Django REST framework generates HTML output for different resources. It facilitates interaction with RESTful web service through any web browser. To enable this feature, we should specify text/html for the Content-Type key in the request header.


2 Answers

No need to override all actions, you can just override the "get_queryset()"

class NameserverViewSet(viewsets.ViewSet):
    queryset = Nameserver.objects.all()

    def get_queryset(self):
        if self.kwargs.get('domain_pk'):
            return Nameserver.objects.filter(domain=domain_pk)
        else:
            return super(NameserverViewSet, self).get_queryset()
like image 185
Ahmed Kolsi Avatar answered Sep 17 '22 13:09

Ahmed Kolsi


@Artem, I use a very similar solution in my code. Here is what I did:

I have an entity called Institutions. I created a route for it, like this:

router.register(r'institutions', SecurityViews.InstitutionViewSet, base_name='institutions')

My URLS look like this:

http://127.0.0.1:8000/v1/institutions/
http://127.0.0.1:8000/v1/institutions/1/

The first URL lists all institutions, the second, is the details URL.

Now, I have people whom I want to be members of those institutions. So, for the route, on urls.py, I did this:

institutions_router = routers.NestedSimpleRouter(router, r'institutions', lookup='institution')

institutions_router.register(r'members', SecurityViews.InstitutionMemberViewSet, base_name='institution-members')

Now, I can get the members of a particular institution with the following URL:

http://127.0.0.1:8000/v1/institutions/1/members/

I also had to define the relationships, mapping the pk of the main entity to the child entity, via serializer. I wont post the whole code here, as I imagine you are familiar with the concept.

For me, the solution proposed by @Artem solved the one problem I had: returning a filtered query. It is working fine now.

I hope this will help you.

like image 38
Théo T. Carranza Avatar answered Sep 20 '22 13:09

Théo T. Carranza