partly caching a view method - django

I am using Memcached (with python-memcached binding) with one of my django projects. The scenario is that on the homepage i have:
A Top Bar : (This contains the links to login / User name with a link to the profile)
A Search Form
Few Blocks Of Results
Currently, I am using the cache_page() decorator to cache the whole page as follows:
#cache_page(3600)
def home(request):
# View Code Goes Here
and the above is working as expected. But as the homepage is a publicly accessible page i am facing a problem with one scenario where:
An anonymous user request the home page(the page get's cached if it
is not already).
Now the user logs in and is redirected to the homepage.
The cached homepage loads (Topbar still shows a login link instead of the logged in user's Name and profile link as the page was cached before the user logged in.)
Question:
Is there a way either on template level or on view level, that lets us specify a block we DO NOT want to cache while using cache_page() decorator ?
Please Note: I am aware that we can use {% cache %} template tag or cache.set for each block in the above scenario. But i am specifically looking for a solution where we can use the cache_page() decorator and still be able to specify a block that i do not want cached in a particular view or a template

use CACHE_MIDDLEWARE_ANONYMOUS_ONLY
yet it sounds as a middleware option, it affects #cache_page as well

Related

How can I change the view site link in Django admin, depending on which app is used?

I am making a project where each client have their own app. This is because they have similar pages but not exactly the same so I think it's a good approach(I may be wrong) to just copy one app for each new client. I have not tried it yet, I am still planning for it. I see one problem with the view site link in the admin. I will let the clients use the admin. How can I set the view site link to the main page for the client? One way to solve it would be to leave it as is and have a function checking their user name and redirecting to the right app. But is there any other way to solve this problem?
I don't think it will be a good idea to have applications generated for users as that's too much once you reached a specific amount of users.
they have similar pages but not exactly the same
Then what you should do is to, after getting the user in your view, pass in a different context to your template. Something like:
def my_view(request):
# First assign different context to different users
context = {'data': 'whatever each user gets', 'other': 'put in more than 1 data',}
return render(request, 'myapp/index.html', context)
I will let the clients use the admin
That's not a good idea as the clients MUST be a superuser to view the admin site. Otherwise, you need to change the permissions of a superuser, make a separate superuser if you are the maintainer of the site, and all sorts of trouble. Just take some time and make your own templates.

How to let user create a page via a URL?

I am thinking along the lines of /mysite/blogs/new. I know about add_child and about Routablepage, also the 'permissions route' but I still don't see how to permit page creation via a URL.
I am surprised that there do not appear to be any instructions for doing this, as relying on the admin method surely isn't acceptable for many 'naive' users. Indeed, it took me a while to realise that Wagtail isn't like Wordpress, in the sense of having an 'Add Post' button or the like.
The documentation does not clearly state that users are (apparently) expected to create pages via the Admin section either. In fact, there seems to be an assumption that developers will be familiar with Django, even though a CMS ought to be easier to use IMO.
Just to be clear, I think that Wagtail is great but the instructions leave something to be desired. Perhaps I will attempt to update them myself!
If you have the Edit Bird/Userbar enabled, then it presents a button to add a child page at any point in the page tree so long as you have permission to add one there. If you wish to give naïve users this option then you could make their permissions fairly restrictive, so that they only see this option at certain locations, and they don't see any of the other 'settings' areas of the Admin.
The admin page for adding this does have its own URL: it typically looks like http://www.example.com/admin/pages/13/add_subpage/, where 13 is the ID of the current page. If instead you want to present that link yourself, you can manually add the link in the template as
Add a child page
but first you should ensure that the user has the relevant permission. This is best done in Python, rather than in the template. See https://github.com/wagtail/wagtail/blob/master/wagtail/wagtailadmin/userbar.py for how Wagtail does this.
To get closer to your original request, you could combine all the above with RoutablePageMixin, by creating a route 'add' which redirects to the same URL:
#route(r'^add$')
def add_child_page(self, request):
return redirect(reverse('wagtailadmin_pages:add_subpage', args=[self.pk]))

Single-page login in Django app

I'm currently using out-of-the-box django.contrib.auth to handle authentication in my Django app. This means that the user starts at a log in page and is redirected to the app on successful login. I would like to make my app single-page, including this login process, where a redirect doesn't happen, but maybe a "hot" template switch-out or some fancy client-side div magic (that still remains secure). My Google searching turned up pretty short, the closest solution dealing with putting a log in form on every page.
Any direction or ideas here would be much appreciated. I would obviously prefer to work within the existing confines of django.contrib.auth if possible, but I'm open to all solutions.
I'm not sure I understand your question completely. I think you want to have a single page. If so, put logic in your template that checks to see if the user is authenticated. If not, display a login form that POSTS to the appropriate django.contrib.auth view. You can supply an argument to this view to have it redirect back to your page. When you come back, the user will be authenticated, so you won't display the login form.
Have a look at Django-Easy-Pjax https://pypi.python.org/pypi/django-easy-pjax - it works like a charm and is well documented. Everything you like is being made with AJAX requests: links, forms using GET and forms using POST.
Essentially you only need to add a data-pjax="#id_of_the_container_where_the_result_goes" attribute in your a and form tags.
And the great thing about it: It updates the title and location bar of your browser.
One caveat: If you want to upload files in some form, this is not supported by Easy-Pjax, so you might want to use some workaround jQuery library for that.

Django: caching all but user auth in page

I'm experimenting with various Django 1.3 caching approaches to use for our landing page. This page has results from several database queries as well as user authentication. By far the best-performing solution has been to use the #cache_page decorator to cache the whole view function response. The problem is that user auth also gets cached.
I can create a key in the cache for each user but this seems wasteful; caching the same landing page over and over with the only difference being the user's authentication. I also used template fragment caching and low-level caching for all but the authentication but the performance was nowhere near as good as the #cache_page decorator approach.
Is there a way to get the performance of #cache_page without lots of redundant user-based caching?
Check out this blog post: http://www.holovaty.com/writing/django-two-phased-rendering/
Basically the technique is to wrap your user-specific segments in a template tag that prevents the template engine from rendering them, then cache, and then re-render the cached output to fill out the user details.
Django 1.5 includes a tag called verbatim which can be used instead of the custom raw tag in the post; you'll still need the custom CachedTemplateMiddleware or equivalent though.

memcached caches request?

after caching several views on my django project -#cache_page(60 * 5)- I've noticed that memcached caches the entire view, even the request argument! So if the first user that visits a page is logged in as userxyz, all other anonymous or registered users that will ask the same page will be presented with the page that was cached by user userxyz! Obviously this is not a desired behavior...So can I cache everything on the view, but not the request argument? Or memcached is suitable for anonymous sessions only?
Thanks in advance,
Markos Gogoulos
If you're mixing dynamic and static data on one page, in your case the dynamic data is the logged in user's username, then page caching isn't the right choice. This wouldn't change if you were using file based cache storage instead of memcached.
I suggest trying fragment caching. You can do something like this:
{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}
This will cache the contents of the cache tag for 500 seconds with the identifier sidebar.
You can find more information on caching here:
http://docs.djangoproject.com/en/dev/topics/cache/
If this is a page that is going to be hit very often, for example a welcome page, that you feel would benefit from using page caching over fragment caching (for example the only dynamic data is the user name), then there are a few other options.
Say for example you want to have a completely static page except for a login/logout section at the top which displays different links depending on whether or not the user is logged in then you can check for the existence of an authentication cookie when the page is first loaded and conditionally display different data using javascript.
Memcached is just a backend. It caches whatever you tell it to cache. So really your question is "Is Django's full-page caching suitable for dynamic pages?"
Probably you don't want do cache full-pages, just part's of it. Or only pages for anonymous requests (using CACHE_MIDDLEWARE_ANONYMOUS_ONLY)
Refer to the book
http://www.djangobook.com/en/1.0/chapter13/
You might want to look into template fragments and caching those bits of content that aren't user specific.