Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What base_name parameter do I need in my route to make this Django API work?

I am building a Django application that exposes a REST API by which users can query my application's models. I'm following the instructions here.

My Route looks like this in myApp's url.py:

from rest_framework import routers
router = routers.DefaultRouter()    router.register(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsViewSet)
url(r'^api/', include(router.urls)),

My Model looks like this:

class MyObject(models.Model):
    name = models.TextField()

My Serializer looks like this:

class MyObjectSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyObject
    fields = ('id', 'name',)

My Viewset looks like this:

class MyObjectsViewSet(viewsets.ViewSet):

    def retrieve(self,request,pk=None):
        queryset = MyObjects.objects.get(pk=pk).customMyObjectList()

        if not queryset:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        else:
            serializer = MyObjectSerializer(queryset)
            return Response(serializer.data,status=status.HTTP_200_OK)

When I hit /api/myObjects/60/ I get the following error:

base_name argument not specified, and could not automatically determine the name from the viewset, as it does not have a .model or .queryset attribute.

I understand from here that I need a base_name parameter on my route. But from the docs, it is unclear to me what that value of that base_name parameter should be. Can someone please tell me what the route should look like with the base_name?

like image 746
Saqib Ali Avatar asked Feb 27 '14 23:02

Saqib Ali


People also ask

What is Basename in router Django?

basename - The base to use for the URL names that are created. 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.

How will you declare a route in Django?

To create a route in Django, we will use the path() function that accepts two parameters: a URL and a View function. All the routes are created inside the urlpatterns list. Simply add a new path as below and a new route will be created.

What is Restapi in Django?

REST APIs are an industry-standard way for web services to send and receive data. They use HTTP request methods to facilitate the request-response cycle and typically transfer data using JSON, and more rarely - HTML, XML and other formats.


5 Answers

Try doing this in your urls.py. The third parameter 'Person' can be anything you want.

router.register(r'person/food', views.PersonViewSet, 'Person')
like image 87
Eric Lee Avatar answered Oct 19 '22 04:10

Eric Lee


Let me explain, why we need an base_name in the first place and then let's go into the possible value of base_name.

If you ever used the Django urls without the rest-framework (DRF) before, you would've specified it like this:

urlpatterns = [
    url(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsListView.as_view(), name='myobject-list'),
    url(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsDetailView.as_view(), name='myobject-detail'),
]

Here, if you see, there is a name parameter which used to identify the url in the current namespace (which is app).

This is exactly what django-rest-framework trying to do automatically, since the drf knows whether the view is list or detail (because of viewset). it just needs to append some prefix to differentiate the urls. That's the purpose of base_name (prefix).

In most scenario, you can give the url or resource name as base_name. In your case, base_name=myobject. DRF will generate base_name + view_type as the name parameter like myobject_list & myobject_detail.

Note: Usually, base_name will be automatically obtained from the queryset field (from view), since it's same for all view types in a viewset. But if you specify, get_queryset method instead of queryset, it possibly means you've different queryset for different view types (like list, detail). So, DRF will ask you to specify a common base_name for all the view types for a resource.

like image 33
Sri Avatar answered Oct 19 '22 02:10

Sri


Maybe you just need to set the base_name parameter for your router with the name of the object: MyObject, in your case.

router.register(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsViewSet, base_name="MyObject")

http://www.django-rest-framework.org/api-guide/routers/#Usage

like image 13
Hugo Hernani Avatar answered Oct 19 '22 04:10

Hugo Hernani


this is a useful answer, read for the details.

tl;dr

It is used as the base name of the generated URL patterns (e.g., 'myobject-detail' or 'myobject-list').

like image 4
Balazs Nemeth Avatar answered Oct 19 '22 02:10

Balazs Nemeth


An alternative solution might be to use a ModelViewSet which will derive the basename automatically from the model.

Just make sure and tell it which model to use:

Because ModelViewSet extends GenericAPIView, you'll normally need to provide at least the queryset and serializer_class attributes, or the model attribute shortcut.

like image 2
GreenGuerilla Avatar answered Oct 19 '22 03:10

GreenGuerilla