Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django REST framework - different views for same url depending on http method

I have a REST framework API and I have to dispatch an url to 2 different views, depending on a method.

the architecture is like this:

bookshop/authors/ - lists all authors, with POST - adds an author

bookshop/authors/<author>/ - with GET - gets details for an author, including books

bookshop/authors/<author>/ - with POST - creates a posting of a book for the same author. 

bookshop/authors/<author>/<book>/ - gets a book, no posting

In general, for all my API I'm using Viewsets with Routers.

I tried doing this:

urlpatterns = patterns(
    '',
    url(r'^author/(?P<author>[0-9]+)',
        AuthorViewSet.as_view({'get': 'retrieve'}),
        name='author-detail'),
    url(r'^author/(?P<author>[0-9]+)',
        BookViewSet.as_view({'post': 'create'})),
)

but then it goes to the first url and the viewset checks for methods and throws an exception MethodNotAllowed.

I tried to catch it like this:

try: 
    urlpatterns = patterns( 
    '', 
    url(r'^author/(?P<author>[0-9]+)',  
    AuthorViewSet.as_view({'get': 'retrieve'}), 
    name='author-detail') 
    ) 
except MethodNotAllowed: 
    urlpatterns = patterns( 
    '', 
    url(r'^author/(?P<author>[0-9]+)', 
    BookViewSet.as_view({'post': 'create'})), 
    )

But it doesn't work too.

Is there any way to do it using viewsets?

like image 388
Karina Klinkevičiūtė Avatar asked May 05 '16 15:05

Karina Klinkevičiūtė


Video Answer


1 Answers

The problem is that organizing your API in such a manner breaks RESTful convention. Breaking RESTful convention is not always bad, but usually represents a poor design and certainly means it is harder to user 3rd party software designed around the restframework to support your schema. So my suggestion is to update your API schema to:

GET  bookshop/authors/ - lists all authors
POST bookshop/authors/ - creates an author
GET  bookshop/authors/<author>/ - gets details for an author
POST bookshop/authors/<author>/books/ - creates a book for an author
GET  bookshop/authors/<author>/books/<book> - gets a book

If you need to add postings you can also have (I'm not sure of the relationships between the objects so, not sure if the below accurately represents that relationship).

POST bookshop/authors/<author>/books/<book>/postings - creates a posting
GET  bookshop/authors/<author>/books/<book>/postings/<posting> - gets a posting
like image 107
Rex Salisbury Avatar answered Oct 21 '22 23:10

Rex Salisbury