Home > Net >  Using Django Rest Framework, how can I capture values from an URL to a viewset using routers, not wi
Using Django Rest Framework, how can I capture values from an URL to a viewset using routers, not wi

Time:12-24

I have two models: the first is named Card and has a foreign key (named owner) to the second model (User). I'm trying to write a view that lists all the Cards owned by a User, the client selects the User by changing the URL (not query parameters).

For example, if I make a GET request to /cards/by-user-id/42/, I should get all the Cards owned by the User whose id is 42.

From what I understood, it is possible to achieve this by using an URL pattern like this : path('cards/by-user-id/<int:user_id>', my_view.as_view()) and then in the viewset I can use self.kwargs['user_id'] to get the id and then filter the data. However, I can't find how to do it using routers (more appropriated for djangorestframework). I tried with <int:user_id> in the prefix but it does not pick it up, it just considers it as a normal string, so not only the URL is incorrect (I have to type literally /cards/by-user-id/<int:user_id>/) but also kwargs doesn't contain 'user_id'.

Here is what I tried:

models.py:

from django.contrib.auth.models import User
from django.db import models


class Card(models.Model):
    owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)

serializers.py:

from rest_framework import serializers
from . import models

class CardSerializer(serializers.ModelSerializer):
    owner = serializers.StringRelatedField()

    class Meta:
        model = models.Card
        fields = ['owner', 'id']

views.py:

from rest_framework import viewsets
from . import models, serializers

class ListCardsPerUser(viewsets.ModelViewSet):
    serializer_class = serializers.CardListSerializer

    def get_queryset(self):
        models.CardList.objects.filter(owner__id=self.kwargs['user_id'])

urls.py:

from django.urls import path, include
from rest_framework import routers
from . import views

router = routers.SimpleRouter()
router.register(r'cards/by-user-id/<int:user_id>/', views.ListCardsPerUser, basename='cards_list')

urlpatterns = [
    path('', include(router.urls)),
]

I'm starting to wonder if it is even possible with routers...

Django version: 4.1 and DRF: 3.14

CodePudding user response:

you should just edit your user serializer

class CardASerializer(serializers.ModelSerializer):
    class Meta:
        model = Card
        fields = "__all__"

class UserSerializer(serializers.ModelSerializer):
    cards = CardASerializer(many=True)

    class Meta:
        model = User
        fields = "__all__"

Note that the cards is related_name

class Card(models.Model):
    owner = models.ForeignKey(User, null=True,related_name="cards", on_delete=models.SET_NULL)
  • Related