Saltar al contenido

Filtrado usando conjuntos de vistas en django rest framework

Solución:

ModelViewSet por diseño asume que desea implementar un CRUD (crear, actualizar, eliminar)
También hay una ReadOnlyModelViewSet que implementa solo el GET método para leer solo puntos finales.
Para Movie y Show modelos, un ModelViewSet o ReadOnlyModelViewSet es una buena opción tanto si desea implementar CRUD como si no.
Pero una separada ViewSet para una consulta relacionada de un TimeTable que describe un Movie El horario de la modelo no se ve tan bien.
Un mejor enfoque sería poner ese punto final a un MovieViewSet directamente. DRF lo proporcionó @detail_route y @list_route decoradores.

from rest_framework.response import Response
from rest_framework.decorators import detail_route

class MovieViewSet(viewsets.ModelViewset):

    queryset = Movie.objects.all()
    serializer_class = MovieSerializer

    @detail_route()
    def date_list(self, request, pk=None):
        movie = self.get_object() # retrieve an object by pk provided
        schedule = TimeTable.objects.filter(show__movie=movie).distinct()
        schedule_json = TimeTableSerializer(schedule, many=True)
        return Response(schedule_json.data)

Este punto final estará disponible por un movie-list/:id/date_list url
Documentos sobre rutas adicionales

El error

class DateListViewSet (viewsets.ModelViewSet, movie_id): NameError: el nombre ‘movie_id’ no está definido

sucede porque movie_id se pasa como clase principal de DataListViewSet y no como parámetro como imaginó

Este ejemplo en la documentación debería ser lo que está buscando.

Ajusta tu URL:

url(r'date-list/(?P<movie_id>.+)/', views.DateListView.as_view())

Ajuste su modelo:

class Show(models.Model):
   day = models.ForeignKey(TimeTable, related_name="show")
   time = models.TimeField(choices=CHOICE_TIME)
   movie = models.ForeignKey(Movie)

class Meta:
    unique_together = ('day', 'time')

Su vista se vería así:

class DateListView(generics.ListAPIView):
     serializer_class = TimeTableSerializer

     def get_queryset(self):

         movie = Movie.objects.get(id=self.kwargs['movie_id'])

         return TimeTable.objects.filter(show__movie=movie).distinct()

Otra forma de hacerlo sería:

Ajusta tu URL:

router.register(r'date-list', views.DateListViewSet)

Ajuste su modelo:

class Show(models.Model):
   day = models.ForeignKey(TimeTable, related_name="show")
   time = models.TimeField(choices=CHOICE_TIME)
   movie = models.ForeignKey(Movie)

class Meta:
    unique_together = ('day', 'time')

Su vista se vería así:

class DateListViewSet(viewsets.ModelViewSet):
     serializer_class = TimeTableSerializer
     queryset = TimeTable.objects.all()
     filter_backends = (filters.DjangoFilterBackend,)
     filter_fields = ('show__movie_id')

Lo cual te permitirá realizar solicitudes como:

http://example.com/api/date-list?show__movie_id=1

Ver documentación

Registre su ruta como

router.register(r'date-list', views.DateListViewSet)

ahora cambie su conjunto de vistas como se muestra a continuación,

class DateListViewSet(viewsets.ModelViewSet):
    queryset = TimeTable.objects.all()
    serializer_class = TimeTableSerializer
    lookup_field = 'movie_id'

    def retrieve(self, request, *args, **kwargs):
        movie_id = kwargs.get('movie_id', None)
        movie = Movie.objects.get(id=movie_id)
        self.queryset = TimeTable.objects.filter(show__movie=movie).distinct()
        return super(DateListViewSet, self).retrieve(request, *args, **kwargs)

Utilice un método de recuperación, que hará coincidir cualquier solicitud GET con el punto final /date-list/<id>/.

La ventaja es que no tiene que manejar explícitamente la serialización y devolver la respuesta hace que ViewSet haga esa parte difícil. Solo estamos actualizando el conjunto de consultas para ser serializado y rest framework hace el resto.

Dado que ModelViewSet se implementa como,

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass

Su implementación incluye los siguientes métodos (verbo HTTP y punto final en corchetes)

  • list() (OBTENER /date-list/)
  • create()(CORREO /date-list/)
  • retrieve()(OBTENER date-list/<id>/)
  • update() (PONER /date-list/<id>/)
  • partial_update() (PARCHE, /date-list/<id>/
  • destroy() (ELIMINAR /date-list/<id>/)

Si solo desea implementar el retrieve() (OBTENER solicitudes al punto final date-list/<id>/), puede hacer esto en lugar de un `ModelViewSet),

from rest_framework import mixins, views

class DateListViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    queryset = TimeTable.objects.all()
    serializer_class = TimeTableSerializer
    lookup_field = 'movie_id'

    def retrieve(self, request, *args, **kwargs):
        movie_id = kwargs.get('movie_id', None)
        movie = Movie.objects.get(id=movie_id)
        self.queryset = TimeTable.objects.filter(show__movie=movie).distinct()
        return super(DateListViewSet, self).retrieve(request, *args, **kwargs)
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *