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.
Related
I've written a templatetag that includes much of the logic that I would normally expect to find in a view. While writing some unit tests I started wondering about a slightly different approach. I don't feel experienced enough to judge the pros and cons (maybe this is even a well known practice – or a no go...). That's why I am interested in your opinion.
My idea was to write a view to handle all the logic and to use the templatetag as a wrapper that passes all relevant context to that view and returns the rendered HTML.
Advantages that I would hope to get from this approach:
easier to provide different output formats
easier DRY
easier testing
permission checks using decorators and mixins inside the view
cache control inside the view
nice approach towards ajax and/or edge side includes
higher flexibility
For example, a templatetag that renders a tree navigation could deliver HTML when accessed through the templatetag while at the same time its corresponding view remains accessible through a URL.
The view could provide different output formats like JSON, RSS, XML, handle permission checking, ... Advanced logic could be tested through the view, leaving responsibility for the templatetag testcases just to ensure the very basics.
I'd appreciate other opinions, hints or links to packages or related posts.
In my opinion, the problem with template tags are:
Too much abstraction.
Challenging to test.
Problems with performance
What I suggest instead is:
Create a function that generates the data, caches the data, handles permissions, anything else data related
Write three more functions that render the data in HTML, JSON, and XML respectively
Document and write tests for the above functions
Use these functions in views, filters, and template tags as needed. The views/filters/tags calling the functions would be very thin and easy to manage.
The benefits you get by this approach are:
Reusable code
More easily testable code
Better speed
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)
This is more of a best-practices question, and given that I'm quite tired it mightn't make much sense.
I've been putting together a blog app as a learning experience and as an actual part of a website I am developing.
I've designed it like most apps so that you can list blog posts by multiple criteria i.e.
/blog/categories/
/blog/authors/
/blog/tags/
/blog/popular/
etc.
On each page above I also want to list how many entries are a part of that criteria
i.e. for "categories", I want /blog/categories/ to list all the different categories, but also mention how many blog posts are in that category, and possibly list those entries.
Django seems to give you lots of ways of doing this, but not much indication on what's best in terms of flexibility, reusability and security.
I've noticed that you can either
A: Use generic/very light views, pass a queryset to the template, and gather any remaining necessary information using custom template tags.
i.e. pass the queryset containing the categories, and for each category use a template tag to fetch the entries for that category
or B: Use custom/heavy views, pass one or more querysets + extra necessary information through the view, and use less template tags to fetch information.
i.e. pass a list of dictionaries that contains the categories + their entries.
The way I see it is that the view is there to take in HTTP requests, gather the required information (specific to what's been requested) and pass the HTTP request and Context to be rendered. Template tags should be used to fetch superflous information that isn't particularly related to the current template, (i.e. get the latest entries in a blog, or the most popular entries, but they can really do whatever you like.)
This lack of definition (or ignorance on my part) is starting to get to me, and I'd like to be consistent in my design and implementation, so any input is welcome!
I'd say that your understanding is quite right. The main method of gathering information and rendering it via a template is always the view. Template tags are there for any extra information and processing you might need to do, perhaps across multiple views, that is not directly related to the view you're rendering.
You shouldn't worry about making your views generic. That's what the built-in generic views are for, after all. Once you need to start stepping outside what they provide, then you should definitely make them specific to your use cases. You might of course find some common functionality that is used in multiple views, in which case you can factor that out into a separate function or even a context processor, but on the whole a view is a standalone bit of code for a particular specific use.
The whole point of an MVC framework is to separate design (templates) from logic (controllers). However, template languages often afford a limited degree of "design logic" to occur. This includes basic if statements, loops, filtering, etc.
I've created a Django template tag that can take any list or QuerySet and "pagify" it. It splits the list up into pages based on a specified page size then adds the pages into the Context. The usage is as follows:
{% pagify articles by 20 as pages %}
I can then call a separate include to iterate over the pages and produce a nice list of pages wherever I needed it.
This seemed like an optimal way to do it because it allowed me to page any list in the context; I didn't have to rely on the controller to return paged results. But a colleague argued that this seemed like too much logic for the template. I thought this still fell within the realm of design-based logic since the page would still function even without paging, and determining page size feels like a template responsibility.
My question, is this too much logic for the template? or is this a clean way to be handling this?
It's always been my understanding that the view isn't supposed to be devoid of logic. It's just supposed to be devoid of any controller logic. Paging just has to do with how the data is displayed which is exactly what the view logic is supposed to contain.
Put it this way; what if you were using your data model in another medium, say, not on the web but via some kind of console-based application or background task? Wouldn't it be nice to be able to get "pages" of data through a controller (or manager) rather than having to somehow rely on a template to do this work for you?
While I'd certainly agree that the "look" of the paged data should be handled by your template, the "act" of paging should be left up to a controller (Django view) or even through some kind of custom manager (models.Manager) method.
The view should not contain business logic or navigation logic. What you are describing is presentation functionality (carefully avoiding the l-word here), which can be placed in the view layer.
You may want to check out django-pagination, which provides a similar template tag.
I agree with your colleague; the template should be fed paginated data rather than performing the pagination. The key question, I think, is whether determining page size is a template duty, and I don't think so; I'd say it should be handled at a higher level.
I'm working on a blog application, and I want to have a sidebar that includes a list of all the months the blog has been in existence, to provide links to archives pages. Moreover, I'd like to make this automatically update when the month changes, rather than hardcoding it in the template. Of course, as far as I can tell, this means that I'll have to calculate the list of months in every view, and pass it into every template from every view.
I'd like to avoid this, if possible. Is there a way to calculate the list once and automatically apply it to every template, without having to explicitly pass it into the template from every view?
There are a few possible solutions to your problem.
If you really want to have this on every page on your site a context processor is probably your best choice. Context processors are basic way to inject data into all template contexts. Be aware however that the context processor will be called on every request.
An alternative solution would be to create a custom template tag and use it on a shared base template for all of the pages you wish to have your sidebar. Template tags are a bit more complex to create but they are more flexible.
With either solution you should also look at Django's cache framework. The cache framework makes it pretty easy to temporarily store your calculated values for a while to save some work on each request.
You want a template context processor
Django - having middleware communicate with views/templates
http://docs.djangoproject.com/en/dev/ref/templates/api/?from=olddocs#id1
Django's template inheritance should cover this. You could create a base template that handles your sidebar functionality. Your other views extend this template.
Template Inheritance:
http://www.djangobook.com/en/1.0/chapter04/#s-template-inheritance
A combination of custom template tags as mentioned previously and template fragment caching should do the trick.