Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django REST Framework - multiple models / APIs?

We use Django to build web-app backend, providing RESTful API for Ember app.

So (evolutionally) we started with the following simple structure:

project root
|
|-app1 / models.py .... no views.py
|
|-app2 / models.py .... no views.py
|
|-app3 / models.py .... no views.py
|
\- restapi - provides REST API for app*: huge views.py, huge serializers.py, huge test.py

This is easy to use, especially with the DRF's browsable view:

@api_view(['GET'])
def api_root(request, format=None):
    return Response(
        {
            'users': reverse('current-user-detail', request=request),
            'interfacesettings': reverse('interface-settings', request=request),
            ............................................................     
            'preferences': reverse('preferences', request=request),
        }
    )

Shortly we have got enough models/APIs to make our restapi.app way too complex and messy, and we started to consider using something more logical:

project root
|
|-app1 / models.py .... views.py, serializers.py, tests.py
|
|-app2 / models.py .... views.py, serializers.py, tests.py
|
|-app3 / models.py .... views.py, serializers.py, tests.py
|
\- we do not need rest api anymore (but where will we put our api_root?)

On the other side, we have now all complicated tests (that involve few models) in one place which is convenient. And we reuse serializers's functions a lot. And we have one api_root. So probably we may have something like this:

project root
|
|-app1 / models.py .... views.py (app1 API), serializers.py, tests.py
|
|-app2 / models.py .... views.py (app2 API), serializers.py, tests.py
|
|-app3 / models.py .... views.py (app3 API), serializers.py, tests.py
|
\- restapi - views.py (api_root), tests.py for complicated tests and serializers.py for common functions

Which approach is better? And what are the common best practices here? Is there any open project we can take a look?

like image 972
kostik Avatar asked Apr 02 '14 00:04

kostik


1 Answers

I am building a restful API also with Django like you. What I am doing is letting applications be independent like in your last example.

We have a “core” django application, where we have the api_root in the views and a file named “apis_urls.py” where we organize all the URLs from the different apps.

We also have in this “core” app a file “apis_filters.py” where we have the filters that any app with API can use and “apis_permissions.py” to manage the permissions to use the apis and import on the other apps.

So at the end we are working like this:

project root
|
|-app1 / models.py .... views.py (app1 API), serializers.py, tests.py
|
|-app2 / models.py .... views.py (app2 API), serializers.py, tests.py
|
|-app3 / models.py .... views.py (app3 API), serializers.py, tests.py
|
\- core / views.py (api_root), apis_urls.py,  apis_filters.py,  apis_permissions.py

We make all the tests in their corresponding apps.

And having the apis_urls.py allows us to have all the API URLs like:

http://localhost/api/v1/example1
http://localhost/api/v1/example2

In the main urls.py we have:

url(r'^api/v1/', include('core.apis_urls', namespace='api')),

And on the core app, on the “apis_urls.py”:

urlpatterns = patterns(
'',
    ####### Users Urls
    url(r'^users/$', users_views.UserListAPIView.as_view(), name='users-list-api'),
    url(r'^me/$', users_views.LoggedUserRetrieveUpdateAPIView.as_view(), name='logged-user-detail-api'),
    url(r'^users/(?P<username>[\w.@+-]+)/$', users_views.UserRetrieveAPIView.as_view(), name='users-detail-api'),

    ####### Comments Urls
    url(r'^comments/(?P<pk>[0-9]+)$', comments_api_views.CommentCreateAPIView.as_view(), name='comments-create-api'),
)

I hope this help, is the way I found it more organize.

like image 68
Javier Vieira Avatar answered Nov 09 '22 01:11

Javier Vieira