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.
Related
I want to write custom template loader for my Django app which looks for a specific folder based on a key that is part of the request.
Let me get into more details to be clear. Assume that I will be getting a key on every request(which I populate using a middleware).
Example: request.key could be 'india' or 'usa' or 'uk'.
I want my template loader to look for the template "templates/<key>/<template.html>". So when I say {% include "home.html" %}, I want the template loader to load "templates/india/home.html" or "templates/usa/home.html" or "templates/uk/home.html" based on the request.
Is there a way to pass the request object to a custom template loader?
I've been searching for the same solution and, after a couple days of searching, decided to use threading.local(). Simply make the request object global for the duration of the HTTP request processing! Commence rotten tomato throwing from the gallery.
Let me explain:
As of Django 1.8 (according to the development version docs) the "dirs" argument for all template finding functions will be deprecated. (ref)
This means that there are no arguments passed into a custom template loader other than the template name being requested and the list of template directories. If you want to access paramters in the request URL (or even the session information) you'll have to "reach out" into some other storage mechanism.
import threading
_local = threading.local()
class CustomMiddleware:
def process_request(self, request):
_local.request = request
def load_template_source(template_name, template_dirs=None):
if _local.request:
# Get the request URL and work your magic here!
pass
In my case it wasn't the request object (directly) I was after but rather what site (I'm developing a SaaS solution) the template should be rendered for.
To find the template to render Django uses the get_template method which only gets the template_name and optional dirs argument. So you cannot really pass the request there.
However, if you customize your render_to_response function to pass along a dirs argument you should be able to do it.
For example (assuming you are using a RequestContext as most people would):
from django import shortcuts
from django.conf import settings
def render_to_response(template_name, dictionary=None, context_instance=None, content_type=None, dirs):
assert context_instance, 'This method requires a `RequestContext` instance to function'
if not dirs:
dirs = []
dirs.append(os.path.join(settings.BASE_TEMPLATE_DIR, context_instance['request'].key)
return shortcuts.render_to_response(template_name, dictionary, context_instance, content_type, dirs)
Whenever we test an API in Django Rest Framework using API Request Factory why do we call the view when we are already passing the url .
Look at the following code for better understanding .
request = self.factory.post("/api/v1/menu/", data)
views = MenuResource.as_view({"post": "post"})
response = views(request)
response.render()
self.assertEqual(201, response.status_code)
In the above code we are calling the url as well as calling the view . View is being called for rendering the view on the url but that is not what my use case is . I just want to test the response code . Is there a way of getting the response code without rendering the view as that is an over kill for my use case .
I have looked for other methods except for using API Request Factory but i just wanted to know why does API Request Factory need to call the view . Is there any advantage in comparison to other API Testing modules present in Django Rest Framework.
That is because you are not making a request to the URL.
request = self.factory.post("/api/v1/menu/", data) simply creates a request object for you to use it does not actually make the request.
So testing the view in your case consists of creating a request object and passing it to the view which mimics the way an actual request would be passed and processed by that view.
If you want to send actual request you need to mock a test server which will handle the actual requests.
Sorry if this is a noob question I am still learning. I have passed a variable from python code to a jinja2 HTML template to set up a URL, like this:
Delete
When this link is pressed it should run a query that deletes the entity with that ID. But when the link is pressed it goes to /delete/1827424298 for example, which results in a 404 error as the request handler doesn't exist.
I need to pass that ID back into my python code so it can run a method to delete the entity with that same ID. How do I go about doing this? Using webapp2 if that is important.
class DeleteRequestHandler(webapp2.RequestHandler):
def get():
template = template_env.get_template('myrequests.html')
context = {
'results': results.key.id()
}
self.response.out.write(template.render(context))
EDIT: I've added my delete handler - it is incomplete as I have yet to add the query to delete the entity. My thinking behind it so far is I can grab the results.key.id() from the jinja2 template and put it into results but I am not sure if this would work.
So I think what you're confused about is how to set up a route handler with a dynamic part to the URL. It's a shame that this is completely skipped over in the webapp2 tutorial, as it's a fundamental part of writing any web application. However, it is covered well in the guide to routing, which you should read.
At its simplest, it's just a matter of putting a regex in the route:
app = webapp2.WSGIApplication([
...
(r'/delete/(\d+)', MyDeleteHandler),
])
which will now route any URL of the form /delete/<number>/ to your deletion handler.
The ID that you pass in the URL will be the first positional argument to the handler method:
class MyDeleteHandler:
def get(self, item_id):
key = ndb.Key(MyModel, item_id) # or whatever
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')
I'm writing a web app which has a page for admin tasks. One of the tasks is that the admin users must be able to edit other users details. Alas, I've fallen at quite a simple roadblock.
I've set up a very simple jQuery AJAX Get request, successfully transferring a string to the server and back. This is just background, but not the issue. The issue lies in retrieving other user's objects.
At the moment, with a username I know exists, this code which is accessed in views.py, produces a 500 Internal Server Error.
#login_required
def user_edit_getuser(request):
# Like before, get the request's context.
context = RequestContext(request)
inputname = request.GET['inputNameSend']
user_obj = User.objects.get(inputname)
return HttpResponse(inputname) #later will return a JSON String
get takes keyword arguments only: the key is the field to look up.
user_obj = User.objects.get(username=inputname)
Also, you should probably deal with the possibility that the GET request has no inputNameSend key.
For JS development, you can usually see the error page in the Chrome dev tools/Firebug console in the Network tab.