Django: request object to template context transparancy - python

I want to include an initialized data structure in my request object, making it accessible in the context object from my templates. What I'm doing right now is passing it manually and tiresome within all my views:
render_to_response(...., ( {'menu': RequestContext(request)}))
The request object contains the key, value pair which is injected using a custom context processor. While this works, I had hoped there was a more generic way of passing selected parts of the request object to the template context. I've tried passing it by generic views, but as it turns out the request object isn't instantiated when parsing the urlpatterns list.

To accomplish this, you will probably have to create your own middleware. That way, you have full control of the request, both before and after the view function.
Middleware is a very powerful concept, and not as hard to implement as it could seem, but don’t overdo it – it makes it hard to follow the program flow.

I don't necessarily understand your question well enough.
Either you are complaining having to include the RequestContext in all views, in which case you need to write a wrapper that passes RequestContext for you. But you will still have to pass to it the request. If you don't want to pass that too, you may have to create your own middleware as mikl suggests.
Or, you are complaining about having to pass a lot of menu items, in each and every view. Which is wrong way to do it, you need to define a template context processor that ensures these are present in the template by default.

Related

What does this mean in the django documentation about class-based views?

A rookie here. As I am reading the django documentation, I came up with a note that I cannot fully understand.
It says:
Note
While your class is instantiated for each request dispatched to it, class attributes set through the as_view() entry point are configured only once at the time your URLs are imported.
Here is the link:
https://docs.djangoproject.com/en/2.2/topics/class-based-views/intro/
So which one is better? What advantage does each have? I've tried both and cannot experience any difference(Pretty sure that's because I've not considered enough)
If you are passing any values into the as_view() method that are likely to change after the server starts, for example some function call or database query whose return value could change after some users use the website, it will be evaluated only once, while the urls are loaded.
Let's say you are passing in the current time like:
path('about/', GreetingView.as_view(greeting=timezone.now())),
That note simply says that the value of the attribute 'greeting' for GreetingView will stay the same for all requests even if the server runs for a month, since timezone.now() is called only once.
Such arguments are good for reusing a View class with minimal changes. It depends completely on your use case.
For example:
path('add-car/', AddView.as_view(form=AddCarForm)),
path('add-bus/', AddView.as_view(form=AddBusForm)),

Apply decorator to context processor

I'm using Fandjango for a Django Facebook Canvas app.
To use fandjango, you need to wrap all view functions with #facebook_authorization_required, which makes sure you're authorized, then gives you the variable request.facebook.user.
What I want is to make a context processor which defines a few more variables based on this, i.e., I want all my templates to be able to use fb_user as a shortcut for request.facebook.user.
The problem is, I don't know how to use the decorator on the context processor.
Any ideas how I can do this?
There's no need to wrap the context processor. If you've wrapped the view in the first place, then the request will already be annotated with the facebook.user attribute. Since the request is passed to the context processor anyway, you have access to that attribute.
You should probably do a quick check - if hasattr(request, 'facebook') - within the context processor, just to make sure it's being called from a wrapped view.

Is there a way to have something execute for every view in django?

I'm new to Django and coming from Rails, so that may explain my odd questions below:
I have a main layout that has a sidebar that lists the latest updates to the site. That main layout is used for every page in my webapp so every template that is created extends main.html.
For the latest updates section, I just want to get the last 5 updates from posts to the web app every time a page is rendered. I thought about making the sidebar do this through an ajax call once the page is loaded, but I thought this may not be my best option.
I also considered creating a tag to do this for me and then just calling the tag inside of main.html. This is simple enough, but I'd have to write a lot of HTML inside of the tag code, which seems to be a little annoying (a lot of string appending and such, unless I'm wrong and there is a better way?)
I have read about Context Processors. This seemed to be exactly what I wanted, but it appears this may cause another issue where I have to pass a context_instance to every single render_to_response? This appears to be a lot of code repeat and I'm trying to avoid that if possible. Is there a way to just make render_to_response always take the RequestContext object without always having to specify it?
Are there any other ways to achieve having some code run for every view and eliminate the need to always pass data to a view?
Django 1.3 added the render shortcut which is the same as render_to_response but with RequestContext automatically used.
Templates is a appropriate place for this: the variant with custom tag and template inheritance is simple and convenient. To avoid string appending use mini-template just for your tag: it is called inclusion tags.
I would definitely go for the Ajax call, it is as simple as to create an small view which queries the model for the 5 latest posts, serializes them into json or xml data, and returns them in your HttpRequest object.
You can use direct_to_template instead of render_to_response.

Django: How do I update a model after a view has been rendered?

I have a view that displays a list of models. Some of the properties of some of the models need to be updated after the view has been rendered: that is, the user is expected to see the original, unchanged values on first visit and the updated values on successive visits (or upon page reload).
I thought I could achieve this with class-based generic views. The official documentation hints at "doing some extra work before or after calling the generic view" (emphasis mine), but all examples given affect the models before it is displayed.
I looked into signals, but to no avail.
Spawning an asynchronous task is an option, but, since all I need to do is update a field in a few models (likely one or none) and save them, it seems overkill for the task at hand.
One could use an ajax request to trigger the update, or a custom template tag to display the relevant fields and update them thereafter. I dislike both, as they move application logic into the view layer. The ajax technique also adds the overhead of a second request.
Yet, I seem to have no other choices, or do I? Is there a more practical technique for plugging into the generic view or the request and execute extra logic after the template has been rendered?
There's no need for anything clever here. Rendering a template doesn't need to be the end of the view - that only comes when you actually return that as a response. They don't have to be in the same step.
So :
def my_view(request, params):
#...do something...
response = render_to_response('my_template.html', {'foo': bar})
# ...do something after rendering...
return response
Now, if you need to do this in a lot of views, you might want to do it in a decorator:
def my_decorator(view):
def my_func(request, params):
response = view(request, params)
#...do something after rendering...
return response
return my_func
now you can decorate your views with #my_decorator and the action will be performed after rendering.
... or, it just occurred to me, if you want to do it in every view, you could do it in a middleware (just define the process-response method).
Edit after comment Class-based generic views use the new TemplateResponse class. You can add tasks that happen after the template is actually rendered with a post-render callback.
Catch the return value from the view or function, do some processing, then kick it up the stack.
def foo(*args):
ret = bar(*args)
do_something()
return ret
Could you grab two copies of the object, modifying and saving one while passing the other (unmodified and outdated) one to the view?
I haven't used class-based generic views yet, so I can't give you a specific example.
Django also comes with a built-in signal request_finished, that is sent AFTER django finished processing the request.
If your project already use celery, you could create a task to update the model and
and call
your_task.delay()
You could use the countdown argument to specify an elapsed before launching the task.
If you are not using celery chances are that you will in the future :)

How can you dispatch on request method in Django URLpatterns?

It's clear how to create a URLPattern which dispatches from a URL regex:
(r'^books/$', books),
where books can further dispatch on request method:
def books(request):
if request.method == 'POST':
...
else:
...
I'd like to know if there is an idiomatic way to include the request method inside the URLPattern, keeping all dispatch/route information in a single location, such as:
(r'^books/$', GET, retrieve-book),
(r'^books/$', POST, update-books),
(r'^books/$', PUT, create-books),
The reason it's done as a single view method is that you're usually rendering some kind of page content as context for the form you're about to submit.
Anyway, my reason for replying it this: from your sample URLConf there it looks like you're building a REST webservice with Django -- if this is the case, you might really benefit from using the rather good django-piston to automatically create your resources/collections. It uses class-based handlers that automatically redirect to the appropriate method (get-books, update-books, create-books in your case) based on the HTTP method in the request
UPDATE (four years later!) while django-piston still exists (and works), Django REST Framework is a much more sophisticated, documented and extended choice these days.
Standard Django doesn't have any mechanism for differentiating request methods besides what you used in your second snippet:
if request.method == 'POST':
...
However, there are third-party apps and snippets that attempt to make method handling a little cleaner using class based views. See, for example, this snippet (found from this SO question about class views).
Personally I'm not so sure this is a good idea. The standard Django method is so... standard... that I think this introduces extra confusion and complexity where it really isn't needed.

Categories

Resources