Home > Back-end >  Setting a route for a specific method in Django
Setting a route for a specific method in Django

Time:09-14

I'm working with REST API in django from scratch. I mean, I'm not working with DjangoRestFramework directly, but i am using Class-BasedViews and some things from RestFramework. So, I am trying to return a GET response for all my actors but the problem is that I already have another GET response into my urls.py for the list of movies and Django returns the one who is first. Do you have any idea to solve this?

Here is my Models, Views, and urls.py

class Actor(models.Model):
    full_name = models.CharField(max_length=125)
    role = models.CharField(max_length=125)

    def __str__(self):
        return self.full_name

    @classmethod
    def find_actors(cls):
        actors = Actor.objects.all().order_by('pk')
        actors_list = []
        for actor in actors:
            actors_list.append({
                "full_name": actor.full_name,
            })

        return actors_list


class Movie(models.Model):
    ACTION = 'AC'
    DRAMA = 'DR'
    COMEDY = 'CM'
    SCIENCE_FICTION = 'SF'
    THRILLER = 'TR'
    RELIGIOUS = 'RG'

    GENRE_CHOICES = [

        (ACTION, 'Accion'),
        (DRAMA, 'Drama'),
        (COMEDY, 'Comedy'),
        (SCIENCE_FICTION, 'Ciencia Ficcion'),
        (THRILLER, 'Triler'),
        (RELIGIOUS, 'Religioso')
    ]

    title = models.CharField(max_length=155, blank=False)
    synopsis = models.TextField(max_length=1000, blank=True)
    genre = models.CharField(max_length=100, choices=GENRE_CHOICES, default='', blank=False)
    tag = models.JSONField(default=dict, blank=True)
    actors = models.ManyToManyField(Actor, related_name='movies', blank=True)

    def __str__(self):
        return self.title

    @classmethod
    def find_all_movies(cls):
        movies = Movie.objects.filter(actors__isnull=False).distinct().order_by('pk')
        movie_list = []
        for movie in movies:
            movie_list.append({
                "id": movie.id,
                "title": movie.title,
                "synopsis": movie.synopsis,
                "genre": movie.genre,
                "tag": movie.tag,
                "actors": list(movie.actors.all().values('full_name', 'role'))
            })

        return movie_list

views.py

class MovieView(APIView):
    permission_classes = [IsAuthenticated]

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, pk=0):
        """
        Return the list of all movies, or a single movie
        :param pk:
        :param request:
        :return:
        """
        if pk > 0:
            movies = list(Movie.objects.filter(pk=pk).values())
            if len(movies) > 0:
                movie = movies[0]
                data = {'message': "Success", 'movie': movie}
            else:
                data = {'message': "Movie not found... "}
            return Response(data)
        else:
            movies = Movie.find_all_movies()
            if len(movies) > 0:
                data = {'message': "Success", 'movies': movies}
            else:
                data = {'message': "Movies not found ..."}
            return Response(data)

    def get_list_of_actors(self, request):
        actors = Actor.find_actors()
        if len(actors) > 0:
            data = {'message': "Success", 'actors': actors}
        else:
            data = {'message': "Actors not found..."}

        return Response(data)

urls.py

from django.urls import path
from .views import *


urlpatterns = [
    path('movies/', MovieView.as_view(), name='movies-list'),
    path('create-new-movie/', MovieView.as_view(), name='create-new-movie'),
    path('movie-detail/<int:pk>/', MovieView.as_view(), name='movie-detail'),
    path('update-movie/<int:pk>/', MovieView.as_view(), name='update-movie'),
    path('delete-movie/<int:pk>/', MovieView.as_view(), name='delete-movie'),

    path('actors/', MovieView.as_view(), name='actors-list'),
]

CodePudding user response:

you can put a condition on your get method, and decide return which result depend on the url path.

def get(self, request, pk=0):
    if request.path_info == '/movies/':
        return self.get_list_of_movies(request, pk)
    elif request.path_info == '/actors/':
        return self.get_list_of_actors(request)


def get_list_of_movies(self, request, pk):
    """
    Return the list of all movies, or a single movie
    :param pk:
    :param request:
    :return:
    """
    if pk > 0:
        movies = list(Movie.objects.filter(pk=pk).values())
        if len(movies) > 0:
            movie = movies[0]
            data = {'message': "Success", 'movie': movie}
        else:
            data = {'message': "Movie not found... "}
        return Response(data)
    else:
        movies = Movie.find_all_movies()
        if len(movies) > 0:
            data = {'message': "Success", 'movies': movies}
        else:
            data = {'message': "Movies not found ..."}
        return Response(data)


def get_list_of_actors(self, request):
    actors = Actor.find_actors()
    if len(actors) > 0:
        data = {'message': "Success", 'actors': actors}
    else:
        data = {'message': "Actors not found..."}

    return Response(data)

P.S. Although I recommend that use separate views for each of them.

  • Related