Wrapping a non-generic Django view - django

I want to inject one additional variable into the context of a view that belongs to a 3rd-party application without editing the code of that application. Is there a way to do this by wrapping the (non-generic) view? It doesn't accept an extra_context parameter, so the approach described in this SO thread won't work. I know I could create a context processor, but that seems like a lot of overhead, having this variable available on every page when I just want it in one view. Or is there a way to narrow the scope of a context processor?

I think a context processor is the way to go, but with a splash of logic in there that checks the request path (for instance) and only bothers digging out and setting the variable for the occasions when it's needed

Related

Django custom view of a third party app

Lets say I have installed a 3rd party app called 'articles', the app contains basic templates and views. And there is a view called 'home' to list articles.
I need to add a form within that view and of course the form variable is not in the default 'home' view. How should I go about adding the form variable to that view?
There are a couple of ways I can think of right now:
Create another app and create a custom view.
This seems crazy and I won't do it, but for the sake of possibility, add a context processor to add the form variable into the context.
Just wondering if anyone had this situation and what is the best approach for this?
well, you may want to try a Function Decorator to redefine the previous view function.
the context processor or the middlerware is not recommend because it's global and dirty.
another use way I can thing is use-defined tags. This may takes more affort and go against the origin design of the tags. But it seem to be a good way.

Application logic in view code

Should I be writing application logic in my view code? For example, on submission of a form element, I need to create a user and send him an activation email. Is this something to do from a view function, or should I create a separate function to make it easier to test down the road? What does Django recommend here?
I found it very hard to figure out where everything goes when I started using django. It really depends on the type of logic you are writing.
First start with the models: model-methods and managers are a good place to perform row-level logic and table level logic i.e. a model manager would be a good place to write code to get a list of categories that are associated with all blogposts. A model method is a good place to count the characters in a particular blogpost.
View level logic should deal with bringing it all together - taking the request, performing the necessary steps to get to the result you need (maybe using the model managers) and then getting it ready for the template.
If there is code that doesn't fit in else where, but has a logical structure you can simply write a module to perform that. Similarly if there are scraps of code that you don't think belong, keep a utils.py to hold them.
You shouldn't perform any logic really in your templates - instead use template tags if you have to. These are good for using reusable pieces of code that you you neither want in every request cycle nor one single request cycle - you might want them in a subset (i.e. displaying a list of categories while in the blog section of your website)
If you do want some logic to be performed in every request cycle, use either context processors or middleware. If you want some logic to be performed only in one single request cycle, the view is probably the place.
TLDR: Writing logic in your view is fine, but there are plenty of places that might be more appropriate
Separating the registration code into it's own function to make testing easier is a good reason. If you allowed admins to register users in a separate, private view, then a registration function would be more DRY. Personally, I don't think a little application logic in the code will do to much harm.
You might find it instructive to have a look at the registration view in the django-registration app -- just to see how it's written, I'm not saying you should or have to use it. It has encapsulated the user registration into it's own function (there's a level of indirection as well, because the registration backends are pluggable).

Using the Coldbox framework, is there a way to intercept a renderView call and execute a different template?

I am trying to learn Coldbox to perhaps replace the current framework I am using. One of the features that I currently use is the ability to override any of the template inclusions by convention.
Essentially, lets say I have a view, "views/home.cfm"
<h1>I am the default theme</h1>
and that is all well and good. But lets say that I have a different view, "themes/[theme-name]/views/home.cfm"
<h1>I am the user chosen theme</h1>
that I want to include conditionally (say there is a cookie to determine what theme is in use). Also, if the file does not exist, the default/fallback view should be rendered.
Is there any way of doing this overriding the system functions?
I looked at interceptors, and the preViewRender and postViewRender interceptors seem like the place to do something like this, but there doesn't seem to be any way of manipulating the actual workflow. If seems to be mainly pre/post processing of the content. For instance, there doesn't seem to be a way to "return false" to tell the renderView method to not actually render the view. Or any way to affect the location in which the view is to be found.
Any ideas?
Tyler,
The ColdBox Framework is quite flexible. It is possible to do what you desire but I don't think modifying renderView() is the best way to resolve this--although, you most definitely can.
I would encourage you to create a User Defined Function in the /includes/helpers/ApplicationHelper.cfm file that contains the logic you require. The functions that are added to this helper file are accessible from anywhere in the framework. This would allow you to create a function called "renderSkin()" that contains the logic you need. RenderSkin() would ultimitly call "renderView()" when you finally figured out which template you wanted to render for that user.
Respectfully,
Aaron Greenlee
I would suggest you go with the interceptor route, but change the layout instead of the view.
From the postEvent interceptor you can get the processedEvent key from the interceptData to change the layout.
Otherwise you could just make the check part of the layout page. The layout can the be a switch statement (or a more OO approach) $including the themed layout files as needed. This has the advantage of giving you a chance to emit custom interception points and having common functionality (css, js)

how to overwrite django template render method handling

In my application, I am sending periodic cron and background task requests to refresh the cache of pages. While sending a force_refresh kwarg from the view is easy, there's no apparent way to send the force_refresh kwarg to methods being accessed from the template. There are plenty of these I'm using, and it would just make things more complex to start calling all these methods from the view.
So I've been trying to overwrite the template render method so that I pass in the force_refresh kwarg whenever a method is being accessed, if the given response is for a background task request.
I realize that it might simply lead to unexpected problems to add this kwarg to all methods being called, and a try/except ArgumentError block wouldn't exactly be a robust solution, if you have any recommendations about a better way to handle this (hopefully besides accessing each of these methods from the view!), it would be useful to hear them.
Sorry, but your use case is precisely what the view function is for.
In the view function you gather all the data. From this you create a dictionary of the latest data which will be used by the template.
All logic goes in the view. The template has minimal processing.

Calling small app in template

Lets say I have a website with a small application that lists the 10 newest members, or something dynamic like that. I want this to view on every page, perhaps in a sidebar. How would i go about doing this.
My thoughts on the matter. I might not get the whole django thing just yet, but when I have a url like /foo/ calling a view bar - but what info do I have to send to the template from this view. Does every view have to send the info to the template (just so I can view my app) or is there someway to call this from the template instead.
I have tried to read through the documentation, but its seems I just can't understand this.
The usual way to provide '10 newest members' type of information from other apps is via a template tag. See this article by James Bennett on best practices (although note it's a bit out of date, as it was written before the inclusion_tag and simple_tag shortcuts were available).
Create a template tag that you can call on the page
Create a context processor and inject extra context variables onto each pageload
I'm sure there are other ways of doing this but those are probably the most logical two. The first gives you more power and will waste less processing time (for pages where you don't want to display the data) but a context processor is much more simple to write (you don't have to bend over backwards to please the template_tag gods).
Both are valuable things to know so there you go. Go and learn!
"Does every view have to send the info to the template (just so I can view my app)"
Yes.
"Is there someway to call this from the template instead."
No.
Your views are just functions. Functions can call other functions. That's ordinary good design. You can still do ordinary good design in Django.
You do have the ability to provide a "context". This is still done in the views to provide additional "context" for the templates. See http://docs.djangoproject.com/en/dev/ref/templates/api/#writing-your-own-context-processors for writing your own context processor.
Nothing (well almost nothing) is done in the template except render the objects provided by the view into HTML (or XML).
If you have a page that is an amalgamation of stuff from many small apps, then you have two tiers of apps.
Independent Apps.
Composite Apps that depend on Composite or Independent Apps.
Your composite app can call other app view functions to gather data.
Your composite app template can include other app template elements to present that data.
You have all the power of Python to decompose the independent apps into "data production" functions, view functions, template components and final page templates.
An independent app Page will use a view function and a template. The view function will use the data production functions. The template will use template components.
Decomposition still works, even in Django.