Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django equivalent of rail respond_to

In Rails, I can use respond_to to define how the controller respond to according to the request format.

in routes.rb

 map.connect '/profile/:action.:format', :controller => "profile_controller" 

in profile_controller.rb

def profile
      @profile = ...
      respond_to do |format|
        format.html {  }
        format.json {  }

      end
end

Currently, in Django, I have to use two urls and two actions: one to return html and one to return json.

url.py:

urlpatterns = [
    url(r'^profile_html', views.profile_html),
    url(r'^profile_json', views.profile_json),
]

view.py

def profile_html (request):

   #some logic calculations

   return render(request, 'profile.html', {'data': profile})

def profile_json(request):

  #some logic calculations

  serializer = ProfileSerializer(profile)

  return Response(serializer.data)

With this approach, the code for the logic becomes duplicate. Of course I can define a method to do the logic calculations but the code is till verbose.

Is there anyway in Django, I can combine them together?

like image 679
Kelvin Tan Avatar asked Dec 17 '22 22:12

Kelvin Tan


2 Answers

Yes, you can for example define a parameter, that specifies the format:

def profile(request, format='html'):
    #some logic calculations

    if format == 'html':
        return render(request, 'profile.html', {'data': profile})
    elif format == 'json':
        serializer = ProfileSerializer(profile)
        return Response(serializer.data)

Now we can define the urls.py with a specific format parameter:

urlpatterns = [
    url(r'^profile_(?P<format>\w+)', views.profile),
]

So now Django will parse the format as a regex \w+ (you might have to change that a bit), and this will be passed as the format parameter to the profile(..) view call.

Note that now, a user can type anything, for example localhost:8000/profile_blabla. You can thus further restrict the regex.

urlpatterns = [
    url(r'^profile_(?P<format>(json|html))', views.profile),
]

So now only json and html are valid formats. The same way you can define an action parameter (like your first code fragment seems to suggest).

like image 119
Willem Van Onsem Avatar answered Dec 30 '22 13:12

Willem Van Onsem


From your use of serializer classes, you are obviously using Django Rest Framework. Therefore you should let that library do the work here, via its use of renderers - see the documentation.

In your case you want to switch between JSONRenderer and TemplateHTMLRenderer, and DRF will automatically detect which one to use based on either the Accept header or the file extension in the URL.

like image 21
Daniel Roseman Avatar answered Dec 30 '22 14:12

Daniel Roseman