Shashishekhar Hasabnis
Shashishekhar Hasabnis

Reputation: 1756

Django Rest Framework urls.py getting messed up

I am having my models.py file defined as below:-

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

class Custom_User(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    mobile = models.CharField(max_length=20)
    REGISTRATION_CHOICES = (
        ('Learner', 'Learner'),
        ('Trainer', 'Trainer'),
    )
    primary_registration_type = models.CharField(max_length=15, choices=REGISTRATION_CHOICES)    

    def __str__(self):
        return self.user.email

As you can see that my Custom_User model uses Django's User model as its foreign Key.

For the above model I have defined my serialziers.py file like this:-

from django.contrib.auth.models import User
from rest_framework import serializers
from .models import *

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email')


class Custom_UserSerializer(serializers.HyperlinkedModelSerializer):
    user = UserSerializer()
    class Meta:
        model = Custom_User
        fields = ('__all__')

Now I am using this serializers in my viewsets like below:-

from django.contrib.auth.models import User
from rest_framework import viewsets
from .serializers import *


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer



class Custom_UserViewSet(viewsets.ModelViewSet):
    queryset = Custom_User.objects.all()
    serializer_class = Custom_UserSerializer



class TrainerViewSet(viewsets.ModelViewSet):
    queryset = Custom_User.objects.filter(primary_registration_type="Trainer")
    serializer_class = Custom_UserSerializer


class LearnerViewSet(viewsets.ModelViewSet):
    queryset = Custom_User.objects.filter(primary_registration_type="Learner")
    serializer_class = Custom_UserSerializer

And Finally inside my urls.py file I register them as below:-

from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'users', api_mailing_list_views.UserViewSet)
router.register(r'custom_users', api_mailing_list_views.Custom_UserViewSet)
router.register(r'trainers', api_mailing_list_views.TrainerViewSet)
router.register(r'learners', api_mailing_list_views.LearnerViewSet)


urlpatterns = [
    path('admin/', admin.site.urls),
    path('', mailing_list_views.index, name='index'),
    path('api/', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

As I was expecting the urls list to be like below in my browser:

{
    "users": "http://localhost:8080/api/users/",
    "custom_users": "http://localhost:8080/api/custom_users/",
    "trainers": "http://localhost:8080/api/trainers/",
    "learners": "http://localhost:8080/api/learners/"
}

But what i get instead is a list of urls like this:-

{
    "users": "http://localhost:8080/api/users/",
    "custom_users": "http://localhost:8080/api/trainers/",
    "trainers": "http://localhost:8080/api/trainers/",
    "learners": "http://localhost:8080/api/trainers/"
}

However I am not getting any errors or if I visit the following url:-

http://localhost:8080/api/learners/

which is not showing up in the urls list I still get the filtered list of learners in JSON format.

Thanks for the help in advance.

Upvotes: 0

Views: 120

Answers (2)

Bernhard Vallant
Bernhard Vallant

Reputation: 50786

Django-rest-framework's router tries to identify the viewset by its model/queryset, since both viewsets use the same model things most likely get mixed up. From the documentation:

If unset the basename will be automatically generated based on the queryset attribute of the viewset, if it has one. Note that if the viewset does not include a queryset attribute then you must set basename when registering the viewset.

Try providing a basename to the router:

router.register(r'custom_users', api_mailing_list_views.Custom_UserViewSet, basename='custom_users')
router.register(r'trainers', api_mailing_list_views.TrainerViewSet, basename='trainers')
router.register(r'learners', api_mailing_list_views.LearnerViewSet, basename='learners')

Upvotes: 2

Shakil
Shakil

Reputation: 4630

you need to provide basename during router register as all of them actually from same custom_user model.

router = routers.DefaultRouter()
router.register(r'users', api_mailing_list_views.UserViewSet, basename='users')
router.register(r'custom_users', api_mailing_list_views.Custom_UserViewSet, basename='custom_user')
router.register(r'trainers', api_mailing_list_views.TrainerViewSet, basename='trainers')
router.register(r'learners', api_mailing_list_views.LearnerViewSet, basename='learners')

Upvotes: 2

Related Questions