I want to store (in files) all request/response pairs of views in a Django app.
How to do this?
I could probably use tcpflow, but would prefer to use a Python solution in Django itself rather than external programs like tcpflow (which also requires root privileges, what I dislike).
You can create a middleware, something like (adapted the example from the doc):
def simple_middleware(get_response):
def middleware(request):
response = get_response(request)
# SAVE REQUEST AND RESPONSE HERE
return response
return middleware
And adding it to the MIDDLEWARE setting.
Related
I have a complex DRF ViewSet that supports paging, filtering, sorting, etc. that backends a grid view. To build an "export" capability, I need to be able to take the same querystring that my endpoint uses, such as:
?obj_id=129&ordering=latitude&city__icontains=nap
And be able to, in Django, send that string into DRF somehow and get the fully-modified queryset after all the view's filters, sorts, etc are applied (the same way as the GET did). I could use the fully-rendered json response or some interim filter-applied queryset. Is it possible to use DRF in this way?
You should write a CSV renderer for your viewset and get that content-type to export the CSV.
There's even one already available.
Yes you could, if you already have a request object i.e. If you want to use this DRF viewset into another view which has the request object:
def another_view(request):
# make a copy of the `GET` attribute of request object
request.GET = request.GET.copy()
# now you can set the query params on this GET object
# ?obj_id=129&ordering=latitude&city__icontains=nap
request.GET['obj_id'] = 129
request.GET['ordering'] = 'latitude'
request.GET['city__icontains'] = 'nap'
# you can also set paging options in similar way
# now instantiate the viewset
vs = DRFViewset.as_view()
# call the view for response
# set kwargs as you need
response = vs(request, *args, **kwargs)
# response.data will have what you want here
It seems like they have a gzip_page decorator for views
from django.views.decorators.gzip import gzip_page
#gzip_page
def viewFunc(request):
return HttpResponse("hello"*100)
Reference here: https://docs.djangoproject.com/en/1.4/topics/http/decorators/#module-django.views.decorators.gzip
as well as a middleware class you can add to settings and then use.
MIDDLEWARE_CLASSES = (
django.middleware.gzip.GZipMiddleware,
...
)
from django.middleware.gzip import GZipMiddleware
gzip_middleware = GZipMiddleware()
def dec(request, *args, **kwargs):
response = func(request, *args, **kwargs)
return gzip_middleware.process_response(request, response)
return dec
Using the page decorator kind of sped up the rendering of a huge ammt. of data (for a table), was wondering which way was best/ what the differences were.
Thanks for any info!
If you look in Django sources, you will see that gzip_page decorator and GZipMiddleware are in fact one and the same thing:
gzip_page = decorator_from_middleware(GZipMiddleware)
So there is no difference at all (apart from some overhead needed to convert middleware to decorator). If you need to enable gzip only for one specific view you should obviously use the decorator, but if you want to have gzip on for the entire project, use the middleware.
As a sidenote, I'm sure you will get much better performance if you leave gzipping to whatever web server you are using (Apache, nginx, etc.)
Also be aware that you shouldn't use gzip for HTTPS protected websites, more on it here: http://breachattack.com/
I am writing a Django based website, but need to serve a a simple text file. Is the correct way to so this by putting it in the static directory and bypassing Django?
If the file is static (not generated by the django app) then you can put it in the static directory.
If the content of this file is generated by Django then you can return it in a HttpResponse with text/plain as mimetype.
content = 'any string generated by django'
return HttpResponse(content, content_type='text/plain')
You can also give a name to the file by setting the Content-Disposition of the response.
filename = "my-file.txt"
content = 'any string generated by django'
response = HttpResponse(content, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename={0}'.format(filename)
return response
I agree with #luc, however another alternative is to use X-Accel-Redirect header.
Imagine that you have to serve big protected (have to login to view it) static files. If you put the file in static directory, then it's access is open and anybody can view it. If you serve it in Django by opening the file and then serving it, there is too much IO and Django will use more RAM since it has to load the file into RAM. The solution is to have a view, which will authenticate a user against a database, however instead of returning a file, Django will add X-Accel-Redirect header to it's response. Now since Django is behind nginx, nginx will see this header and it will then serve the protected static file. That's much better because nginx is much better and much faste at serving static files compared to Django. Here are nginx docs on how to do that. You can also do a similar thing in Apache, however I don't remember the header.
I was using a more complex method until recently, then I discovered this and this:
path('file.txt', TemplateView.as_view(template_name='file.txt',
content_type='text/plain')),
Then put file.txt in the root of your templates directory in your Django project.
I'm now using this method for robots.txt, a text file like the original asker, and a pre-generated sitemap.xml (eg, change to content_type='text/xml').
Unless I'm missing something, this is pretty simple and powerful.
I had a similar requirement for getting a text template for a form via AJAX. I choose to implement it with a model based view (Django 1.6.1) like this:
from django.http import HttpResponse
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from .models import MyModel
class TextFieldView(SingleObjectMixin, View):
model = MyModel
def get(self, request, *args, **kwargs):
myinstance = self.get_object()
content = myinstance.render_text_content()
return HttpResponse(content, content_type='text/plain; charset=utf8')
The rendered text is quite small and dynamically generated from other fields in the model.
I am trying to allow registration (using this django-registration register view) to one of my applications from a modal dialog.
Since this form is in a modal box, I'd like to get an json reponse on success (instead of the default redirection)
How can I use this view (django-registration register) to manage the registration and send back a json response on success ?
I know how to make ajax/json responses, the question is how to use the django-registration view without the redirection behavior or wrap it into an other view to manage the response.
First you need to change the urls.py to wrap the existing view with another functionality. To do that you have to create a new backend package in backends folder and change urls.py there while keeping everything else intact, or you could just go ahead and modify the existing urls.py in the backend package.
I have not tested this, but it should work.
Point url to the new view:
# urls.py
url(r'^register/$', register_wrap,
{'backend': 'registration.backends.default.DefaultBackend'},
name='registration_register'),
# your new view that wraps the existing one
def register_wrap(request, *args, **kwargs):
# call the standard view here
response = register(request, *args, **kwargs)
# check if response is a redirect
if response.status_code == 302:
# this was redirection, send json response instead
else:
# just return as it is
return response
If you are going to need this for more views you can just create a decorator using this.
Why I would do is to check if request.is_ajax() in your normal after-successfull-registration-redirect view and return json response there.
You ask how you can use the existing view to manage the registration and send back a json response on success. Since the HttpResponseRedirect is pretty much hard coded in the view, you can't use the view as it is. Instead, either fork it, or write your own view and change the urls.py so that r'^register/$' directs to your new view.
As far as the json response is concerned, on success you can do something like this:
from django.utils import simplejson as json
def register_ajax(request):
...
return HttpResponse(json.dumps(dict(success=True, **dict_containing_data)))
Hope this helps
I have a web application which will return a user id based on the first segment of the url, much like Twitter:
http://www.myapplication.com/user-name-goes-here/
It can go deeper too, like so:
http://www.myapplication.com/user-name-goes-here/news/article_1/
In order to break the site down, I am using the following URL routing technique:
(r'^(?P<slug>\w+)/', include('myapp.sites.urls')),
This will then further route the user to the correct page, but as it stands I am having to query the database in every view in order to obtain the user_id based on the first url segment. I was hoping to somehow automate this so I don't have to bloat my views with the same code each time... my solution was to create some middleware which checks the url segment and returns a 404 if its not found:
from django.http import Http404
class DomainMiddleware(object):
def process_request(self, request):
from myapp.sites.models import Sites
dname = request.path.split('/')[1]
if not dname:
return
try:
d = Sites.objects.get(domain__exact=dname)
except Sites.DoesNotExist:
raise Http404
return
This works, but it's trying to parse EVERY request, even those to images, favicons etc.
My question is thus; Is there a way to run this query on every page load without clogging up my views with extra code? If middleware is the solution, how can I modify my code so that it doesn't include EVERY request, only those to successfully routed URLs?
Hope someone can help!
The Django server shouldn't be processing requests for static content URLs - certainly not in production anyway, where you'd have a different web server running to handle that, so this shouldn't be an issue there.
But if you say you'd like this to run for only sucessfully routed URLs, maybe you'd be better of using process_view rather than process_request in your middleware? http://docs.djangoproject.com/en/dev/topics/http/middleware/#process-view
process_view works at view level rather than request level, and provides a view_func argument which you can check so that your code doesn't run when it's the django.views.static.serve view used for serving static media during development.
Whatever happens you should defs be caching that database call if it's going to be used on every view.