0

Viewsets in Django Rest Framework keep my code very clean: I can define a model and then a viewset to go along with it.

However, how do I best deal with models which are hierarchically under another one? For example: I have a Project which has many Files and want this API:

  1. GET /api/files: get all files across all projects
  2. GET /api/files/:id: detail a particular file
  3. GET /api/projects/:id/files: list all files in a project

The following code almost works, except that the URL for 3. comes out as api/files/projects/:id:

class FileViewSet(
    mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet
):
    queryset = File.objects.all()
    serializer_class = FileSerializer

    @action(methods=["get"], url_path="projects/(?P<project_id>[^/.]+)", detail=False)
    def list_for_project(self, request, project_id):
        project = Project.objects.get(id=project_id)
        # ... list only Files for this Project

I have looked in to a few solutions such as writing custom routers, using more than one viewset or view, or custom packages; but I'm surprised that it isn't easy to do with DRF out-of-the-box within one Viewset. Am I missing a trick? What do people usually do in this scenario?

1

2 Answers 2

0

For this, you should create relation between 2 different models. In the file model create 1 field with a foreign key association to projects.

class File(models.Model):
    projects = models.ForeignKey(Projects)
Sign up to request clarification or add additional context in comments.

1 Comment

That gives me the needed relation for the Django models, but it doesn't automatically create the REST API that I want.
0

What I understood is you need to simplify the code at the same time you need to do all these three. Usage of mixins is a great way to implement api, but in my opinion I recommend you to use ModelViewSet, for more details click here Its the simplest way in which you don't need to specify the url patterns like projects/(?P<project_id>[^/.]+), I will give you an example code

views.py

from rest_framework import view sets
from django.shortcuts import render
from .models import ModelName
from .serializers import SerializerName

class TestAPIView(viewsets.ModelViewSet):
    queryset = ModelName.objects.all()
    serialiser_class = SerializerName

urls.py

import rest_framework import routers
from .views import TestAPIView


router = routers.DefaultRouter()
router.register('test',TestAPIView, base_name="api-test")
urlpatterns= router.urls  

The first two will work correctly with this way and for the third one, you can deal it with creating multiple model classes projects and files add foreign key relation between these classes example:

class ProjectModel(models.Model):
   ...
   ...

class FileModel(models.Model):
   project = models.ForeignKey(ProjectModel);
   ....
   ....

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.