9

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)),
)
Community
  • 1
  • 1
Artem Fedosov
  • 2,163
  • 2
  • 18
  • 28

3 Answers3

11

Solution came from Alan, the author.

Here is how ViewSet should be implemented:

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

    def list(self, request, domain_pk=None):
        queryset = self.queryset.filter(domain=domain_pk)
        serializer = NameserverSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None, domain_pk=None):
        queryset = self.queryset.get(pk=pk, domain=domain_pk)
        serializer = NameserverSerializer(queryset)
        return Response(serializer.data)
Carles Barrobés
  • 11,608
  • 5
  • 46
  • 60
Artem Fedosov
  • 2,163
  • 2
  • 18
  • 28
  • 1
    Do you have a clue what is misconfigured on [my project](http://stackoverflow.com/questions/29126707/improperly-configured-nested-resource-using-hyperlinkedmodelserializer)? – JJD Mar 18 '15 at 16:05
5

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()
Ahmed Kolsi
  • 211
  • 2
  • 7
2

@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.

Théo T. Carranza
  • 7,813
  • 1
  • 21
  • 14