Profiling for Django + Tastypie - django

What is the best tool to do profiling on a Django app that uses Tastypie (all responses or JSON, so django_toolbar is no good in this case)?

One potential solution is to create a view which just renders TastyPie responses as HTML. This will allow django-debug-toolbar to output correct profiling data. The following is a fairly quick and dirty attempt at this.
In urls.py:
Just add the following line to your url patterns, but make sure it is only included if debugging is enabled.
(r'^api_profile/(?P<resource>.*)$', 'common.views.api_profile')
In common/views.py:
Place this view anywhere you want, I've put it in my common app.
from django.shortcuts import render_to_response
# Import the tastypie.api.Api object with which your api resources are registered.
from apps.api.urls import api
def api_profile(request, resource):
""" Allows easy profiling of API requests with django-debug-toolbar. """
context = {}
resource = resource.strip('/')
resource = api.canonical_resource_for(resource)
obj_list = resource.wrap_view('dispatch_list')(request)
response = resource.create_response(request, obj_list)
context['api_response'] = response
return render_to_response('common/api_profile.html', context)
In templates/common/api_profile.html:
Include a very simple template.
<body>
{{api_response}}
</body>
Now you could just navigate to '/api_profile/a_resource/' with django-debug-toolbar enabled and get profiling data for the generation of the a_resource list view. Request parameters can also be used, e.g. I've been profiling the request 'api_profile/posts/?limit=8&offset=16'.

I've never actually tried profiling a django application. But some time ago I've read an interesting article about this subject.
http://reinout.vanrees.org/weblog/2012/04/18/profiling-python.html

New Relic is good if you want to pay. You can also use hotshot profiler in https://github.com/shaunsephton/django-snippetscream for a quick peek at whats going on

I use this middleware -> https://djangosnippets.org/snippets/2126/
As the comment states, just
Install this by adding it to your MIDDLEWARE_CLASSES. It is active
if you are logged in as a superuser, or always when settings.DEBUG
is True.
To use it, pass 'profile=1' as a GET or POST parameter to any HTTP
request.
It will create an interactive HTML showing queries executed, time, methods... you should give it a try!

Related

How we can get the updated data by refreshing the cache using the cache_page in DRF with the same route?

The website is similar in functionality to Twitter and we're using a Django caching mechanism for the feed but when the user created his post he is not able to find his post for the next 10 minutes due to the caching and we want to show the latest results to the user so, how we can show the latest data to the user after creating his post using the same route
Here is the urls.py code
from django.views.decorators.cache import cache_page
from . import views
CACHE_TIME=60*10
urlpatterns = [
path('', cache_page(CACHE_TIME)(views.PostListAPIView.as_view()), name="post-list")
]
if we call the API --> http://127.0.0.1:8000/v1/posts/ then data will be stored in the cache for the next 10 minutes but I want to refresh after the specific event so, how can we get the updated data before the 10 minutes
also,
We have found a solution for it if we pass http://127.0.0.1:8000/v1/posts/?{username}=true then we can get the latest data for the user but is there any other better approach or possibility to show the latest data? if yes, then please list the method and some details about it
There are many cases you will need to delete the old cache. You will get them soon.
Regarding your issue, I assume that you just need to cover a case: invalidate cache after a post is added.
This is best approach for you:
Using signal to detect when a post is added
From django cache docs, it says that cache.delete('key') should be enough. So just need to use it, and call a function to warm-up the cache if needed then.
Sample code
#receiver(post_save, sender=Post)
def invalidate_post_list_cache(sender, instance, **kwargs):
"""
This signal helps invalidate post list cache and warm-up cache
"""
cache.delete('key')
call_function_to_warm_up_cache()
There are only two hard things in Computer Science: cache invalidation and naming things – Phil Karlton

Django - Runtime database switching

In my work we want to run a server with multiple databases. The databases switching should occur when you acces a url like http://myapp.webpage.com or http://other.webpage.com. We want to run only one server instance and at the moment of the HTTP request switch the database and return the corresponding response.
We've been looking for a mantainable and 'Django-friendly' solution. In our investigation we have found possible ways to do this, but we have not enough information about.
Option 1: Django middleware
The django middleware runs each time the server receive a HTTP request.
Making a database switch here could be the best option but using django database routers as far as I know only allow to change the database for a model or group or models.
Another option is to set a django model manager instance in the middleware and force all models to re-assign the objects attribute from an added attribute in the custom middleware.
My last option is to create a new attribute in the request object received by the middleware that return the database alias from settings.py and in each model query use the using method.
Option 2: Class-based View Mixin
Create a mixin that use the past three options, but I the mixin must be set in ALL the Class-based views. If a programmer forget to set the mixin and it comes to a production server, the data could be (or stop being) in the right database, and I don't wanna take the risk.
Option 3: Changing the database settings in runtime
This option works but Is not recommended and is too risky.
UPDATE:
How this works?
middlewares.py
import django.conf as conf
import os.path
class SelectDB(object):
def process_request(self, request):
print request.META['HTTP_REFERER']
file_database = open("booklog/database.txt", "r")
database = file_database.read(10)
file_database.close()
if database != 'default':
conf.settings.DATABASES['default']['NAME'] = database
Any information that help us to solve will be greatly appreciated.
Answer (it worked for me)
The question was already answered here, in stackoverflow. I'd love this functionality were in django. It was a bit hard to find the way to make this possible.
I think that is important to comment the great work that Wilduck made with the django plugin django-dynamic-db-router, it's a great plugin that makes possible this operation in (a bit) different way.
Thanks a lot to #JL Peyret and #ire_and_curses.
And as an answer to #ire_and_curses. At least in this moment, in the project I'm working it's what we need. In previous projects we needed a similar behavior and made one server per instance was terrible to mantain and update each server, even automating the process.

Can Django-cms pages incorporate the vary_on_headers decorator?

I'm building a site using Django-CMS and we're using MobileESP to detect the user-agent and serve different templates and content depending on what device is being used to the view the site.
The issue is that with django-cms's built in page caching, users are seeing the wrong content depending on which version of the page was cached. For example, if the desktop version of the site is viewed first and then cached, then users visiting the site on a smartphone still see the desktop version instead of the mobile version.
With traditional Django views this could be resolved using the #vary_on_headers('User-Agent') to ensure different versions of the site get correctly cached.
Is it possible to apply this logic to Django-CMS views some how?
I managed to figure out a way to work around this issue by using the patch_vary_headers() functionality in a custom middleware class. I already had a platform detection middleware which added the mobile/desktop setting to the request object. So I just added a process_response function to the middleware and patched it there. So far it appears to be working correctly.
class PlatformDetectionMiddleWare (object):
def process_request(self, request):
user_agent = request.META.get("HTTP_USER_AGENT")
http_accept = request.META.get("HTTP_ACCEPT")
agent = mdetect.UAgentInfo(userAgent=user_agent, httpAccept=http_accept)
request.is_tablet = agent.detectTierTablet()
request.is_mobile = agent.detectTierIphone()
def process_response(self, request, response):
patch_vary_headers(response, ['User-Agent'])
return response
http://www.djangobook.com/en/2.0/chapter15.html I think you can caching like SI Eric suggest and this link talk about caching with vary_header I think it's can help to solve your problem.
I cache on view layer with
#vary_on_headers('User-Agent')
in my project and it run quite well!

Whats the best way to display message after CRUD operation In Django

I have been doing CRUD operation in Django but I am having problem with what to do after successful operation.
Is there any way that i can redirect the user to Home page with small message on top of page like
"Record Successfully added or something else" like Google does with Dismiss hyperlink :)
EDIT:
Actually that a is full documentation and not a simple example.
I could not understand in which template I have to include {{messages}} in. In update form, edit form or home page form?
I don't understand where I need to define messages. I use only generic views so I am confused.
Use the django.contrib.messages framework to get the same messaging style as used in Django admin.
Enable the middleware module by adding 'django.contrib.sessions.middleware.SessionMiddleware' to MIDDLEWARE_CLASSES in settings.py.
In your view, use something like messages.add_message(request, messages.INFO, 'Stuff happened') to record information where it makes sense.
In your template, you'll have a list messages which you can iterate over where it makes sense in your design - the example in the documentation shows a full example which exposes the tags as CSS classes for ease of styling.

Django options for making variables widely available

Every time I open a page I want to get the currently active project id. This will be done by chacking the subdomain and verifying the currently logged in user can view it.
Once I reach my view I want to be able to do
tasks = Task.objects.filter(project = current_project)
WHere current_project (or CURRENT_PROJECT or current_project ???) has already been setup.
Can anyone explain the pros/cons of the various approaches I have found in the docs and put me on the right track?
Sessions
Middleware
Threading
builtins
This was how I did it in the end:
Decorator:
def check4project(fn):
current_project = 'fred'
def check(*args, **kw):
kw['project']=current_project
return fn(*args, **kw)
return check
View example
#login_required
#check4project
#tweetpost
def index(request, project=0):
print project
It all depends on what your semantics of "current project" are. Here are some possibilities:
It could be a characteristic of the user: he visits his profile page and sets a current project. This would be stored in the database, and you would access it with the ORM.
It could be a characteristic of the URL, based solely on subdomain. This could be done with middleware, which has access to the request, and could for example, parse the host name and set a custom attribute on the request that you could access in your view functions.
Similar to #2, you could use a view decorator if checking projects is done for some views but not all. This is similar to Django's decorators for checking authorization.
It could be a characteristic of the user's visit to the site: he visits a page of projects, chooses one to work on, and it's sticky until he chooses another project. This would be best stored in the session, which is specifically for this sort of transient storage.
From your description, it sounsd like #2 or #3 is the best for you, depending on how your views divide up between caring about subprojects and not.
You could make a context_processor and then get your value from the request object.
Have you considered a custom template tag?