I'm new in web dev and I'm trying for a project to develop a Restful web api and a website. I'm using Django framework and following tutos, I always see html files as static and the different views rendering an html template. This way of doing seems to me as backend and frontend are not much separated. Is it possible to have backend only developed in Django ?
edit:
I have actually a problem more specific. I having this app (records) with a view having "patient_list" using Response class from REST framework that renders some data and an html template like this:
def patient_list(request):
"""
List all records, or create a new .
"""
if request.method == 'GET':
#data = Patient.objects.all()
data= Patient.objects.all()
#serializer = PatientSerializer(data, many=True)
#return JSONResponse(serializer.data)
return Response({'patients': data}, template_name='records.html')
in my urls.py I have:
url(r'^records/$', views.patient_list),
and here I'm a little confused. Suppose one called this /records, so patient_list is called and will response with an html page. From what I understood (maybe wrong), a restful API should renders data in a standard view so that it can be used from any "frontend" (html pages or mobile app). Is this statement correct ? am I doing it wrong using Response with an html template ?
With Vanilla Django
Of course it's possible, and without any additional libraries to Django.
E.g. You can define a Django view that returns JSON data instead of rendering it into a HTML template server-side. Effectively making an API instead of a "website".
Here's an example with a class-based view that accepts GET requests and returns some JSON data with JsonResponse
from django.views.generic import View
from django.http import JsonResponse
class MyView(View):
def get(self, request):
my_data = {'something': 'some value'}
return JsonResponse(my_data, mimetype='application/json')
As you can see, you don't have to use the HTML rendering facilities in Django, they're there only if you want to use them.
With REST libraries
And of course there is a host of libraries to build RESTful APIs with Django, like Django REST Framework and Tastypie
Multiple representations and content negotiation
Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences.
You can support more than one format in your REST API. E.g. you can support both HTML and JSON formats. There are various ways to do this:
You may use a GET param ?format=JSON (and have it default to HTML e.g.)
You may use Accept headers
You may have two URLs /records.html and /records.json (the format suffix method)
More on this topic in DRF's documentation
E.g. if you were to implement the first method with the GET params you could modify your code this way:
if request.method == 'GET':
data = Patient.objects.all()
format = request.GET.get('format', None)
if format == 'JSON':
serializer = PatientSerializer(data, many=True)
return JSONResponse(serializer.data)
else:
# Return HTML format by default
return Response({'patients': data}, template_name='records.html')
Related
So hey guys currently I'm trying to create an API endpoint that calls an external API via url with some filtering by comma separated strings. I'm used to creating internal APIs with models and views that call from it's own local sqlite database. But I'm less familiar with this.
For instance I'm trying to have it so when I open my django devserver for this endpoint say called 'api/data?tags=beef,chicken' it gets the JSON response from say 'www.example.com/api/data?tags=beef,chicken' and displays it.
I was thinking about something like the code but wasn't sure how to apply filtering to it without accessing the queryset.
import requests
from rest_framework import status
from rest_framework.response import Response
def external_api_view(request):
if request.method == "GET":
r = requests.get("https://example.com/api/data/")
If you need to send the parameters directly from your local API to the external API you can use this
def external_api_view(request):
if request.method == "GET":
r = requests.get("https://example.com/api/data/", params=requests.GET)
I'm using Django==1.10.5 and djangorestframework==3.5.3.
I have a few ModelViewSets that handle JSON API requests properly. Now, I'd like to use TemplateRenderer to add HTML rendering to those same ModelViewSets. I started with the list endpoint, and created a simple template that lists the available objects. I implemented the get_template_names to return the template I created.
Accessing that endpoint through the browser works fine when there are no objects to list, so everything related to setting up HTML renderers alongside APIs seems to work.However, when tere are objects to return the same endpoint fails with the following error:
ValueError: dictionary update sequence element #0 has length XX; 2 is required
Where XX is the number of attributes the object has.
This documentation section suggests the view function should act slightly differently when returning an HTML Response object, but I assume this is done by DRF's builtin views when necessary, so I don't think that's the issue.
This stackoverflow Q/A also looks relevant but I'm not quite sure it's the right solution to my problem.
How can I make my ModelViewSets work with both HTML and JSON renderers?
Thanks!
DRF has a brief explanation of how to do this in their documentation.
I think you'd do something like this...
On the client side, tell your endpoint what type of response you want:
fetch(yourAPIUrl, {
headers: {
'Accept': 'application/json'
// or 'Accept': 'text/html'
}
})
In your view, just check that and act accordingly:
class FlexibleAPIView(APIView):
"""
API view that can render either JSON or HTML.
"""
renderer_classes = [TemplateHTMLRenderer, JSONRenderer]
def get(self, request, *args, **kwargs):
queryset = Things.objects.all()
# If client wants HTML, give them HTML.
if request.accepted_renderer.format == 'html':
return Response({'things': queryset}, template_name='example.html')
# Otherwise, the client likely wants JSON so serialize the data.
serializer = ThingSerializer(instance=queryset)
data = serializer.data
return Response(data)
In the twilio example made in flask, I can send an SMS and receive an answer using text and the SMS as the search parameter in the database. I need make this but in a django project, my first option that I thought make a django view with a parameter using a url with for send the parameter, but I see that is bad idea because not is possible can use the text of SMS as parameter
This is a part of flask example
#app.route('/directory/search', methods=['POST'])
def search():
query = request.form['Body']
I need make some similar to that view in django using django restframework but how I can get the Body (I think that the body is the text send in the SMS)
for use this as parameter
Use request.POST to access the form data:
from django.shortcuts import render
def my_view(request):
if request.method == "POST":
data = request.POST
# all posted data
data['body']
# the rest of your view logic
return render(request, 'template.html', context)
I have a translation engine api made using Django Python and it has a function that I want to be made into a class based view:
def i18n_newkey(rin):
request = Request(rin, JSONParser())
if request.method == 'POST':
data = json.loads(rin.body)
.... # Parsing and other code here and finally,
return JSONResponse(kdata)
Where the JSONResponse is an HttpResponse that renders it's content into JSON.
My url: url(r'^savekey', 'i18n_newkey'),
I'm new to django and I wanted to convert my function based view to class view, I've read the Django Documentation but I cannot seemed to dig it in this particular code.
Thanks!
Seems like JsonRequestResponseMixin will do exactly what you want.
I'm writing a basic API, where it extends a DetailView to display the latest object for a given model.
As part of the site, django-sekizai is used for django-cms and as a result all used templates need to have the sekizai tags, however these aren't appropriate for an API as it doesn't need CSS/Javascript but rather outputs JSON/XML/Whatever.
Ideally I'd like for sekizai's context processor to not execute for this view, when writing tests such as
class LatestTest(TestCase):
def test_head_empty(self):
c = Client()
response = c.head(reverse(LatestView.plain_view))
I get the error
TemplateSyntaxError: You must enable the 'sekizai.context_processors.sekizai' template context processor or use 'sekizai.context.SekizaiContext' to render your templates.
During the execution of the client request.