10. Beyond simple output
Depends what you want to do.
Modified information
Sometimes you want to modify the information provided by a view. For example, you want to change the query or produce a list of items sorted in particular order.
Django view code can be a difficult subject. Django has some basic response methods builtin. After that Django moves on to class‐based view‐code with a very deep inheritance stack. The classes used contain tricky code. The result is usually clean and tidy, but between the brief documentation, the lack of third‐party documentation, and the bristling, tricky classes, it can be difficult to see what you need to do to achieve an effect. If you do not work with Django as a day‐job, you may need to do much work and meet much trouble. You may need to go to source code, and even that is not easy, due to the deep inheritance and tricks like meta‐programming and decorators.
An example. You have a list view, and you wish to order it. The listView class breaks out the ordering step and exposes it in the API. Once you have found that, your code can be clean as,
That said, you can achieve the same effect, with potential for object selection also, by overriding the get_queryset() method,
Reacting to URLs
So far, we have used Djano generic views to react to URLs. They are doing much work. They get given a model, they check if part of the URL refers to an instance, retrieve the instance then send it to the template. If nothing matches, they return an error page.
What if we need some kind of URL reaction—view code—that is more crude, or refined?
Accessing part of a path element
So you want the grab the last part of these paths in a view, then look at it,
The angle bracketed elements in the following URL paths are called ‘path converters’. The format is ‘<type:name>’. I can’t be bothered listing them, if this interests you, go look at Django documentation.
Simple View
I’m adding defaults so you see how that is done. If you don’t need defaults, delete the appropriate code. urls.py looks like,
A simple view passes the parameter through (in working code, you are more likely to use a TemplateResponse),
Generic View
urls.py looks like,
Bewilderingly, in a generic view, the parameter becomes loaded as an attribute named ‘kwargs’,
Accessing the query of a path
So you want the grab the query parts of these paths in a view, then look at them? Note the wacko format here—for consistency, Django always assumes a trailing ‘/’. Except, no trailing ‘/’ is needed for the query elements. So,
Simple View
Right, well, Django handles query parameters automatically, so you should never try to match them. So urls.py looks like,
The query data is passed in the request,
Generic View
urls.py looks like,
Again, the query data is passed in the request,
About request.GET
It’s a funny immutable object, like a dict. If you use a simple query with no value,
You’ll get a dict‐like object,
You can test for key existence like this,
And, yes, there is a similar request.POST object.
Reacting to a query
I don’t think this guide is the place to dig in, but… starter notes. The methods on an ‘objects’ method on a model can accept a view’s keywords. Which is an ear‐bending sentence so, an example, you can write this in a view,
If you track back to what the kwargs are, they are matched in the URL, so they are a pre‐filtered, pre‐formed set of terms. You can, of course, do more with them than this.
You may need to do more. For example, let’s say you had a model field with a list of countries (for whatever reasons, product source origin etc.). For tidiness, you encoded the countries using an enumerated field of ISO codes e.g. ‘England’ is stored as ‘EN’,
But you want users to be able to search for an ‘england’ match? Can you recover those results from the human title ‘england’? As code, not easy. Best I have come up with—assume the enumeration keys are a precise match to the human codes. Normalise the input to upper‐case, then do a select on the enumeration class (will succeed or fail, depending if the key exists). Then use the resulting type as the filter match,
More normalisation code needed if keys have spaces, like ‘Sierra Leone’. Tangle‐code, used only to express “a caseless match on the country field”. Anyway, there’s an example of how enabling a search, even a simple match, can need thought.
Refs
Python documentation of RequestResponse,
Python documentation of Querydict,
https://docs.djangoproject.com/en/3.2/ref/request-response/#querydict-objects
Extra information
Perhaps you need information from other parts of the database, such as categorisations (for breadcrumbs?)? In which case you need to boost the information going into the template from the view.
To do this, you need to override a view method and call super(). Then you can attach new data to the given context. Bear in mind you can tag in nearly any data. This can be data imported from anywhere, filtered by whatever method you choose. Filtering can be by data that comes specifically from the given URL, which passes through the kwargs. Like this,
Here’s typical kwargs data,
Refs
About halfway down, ‘Adding extra context’,
https://docs.djangoproject.com/en/3.2/topics/class-based-views/generic-display/
Output formatting and template tags
Sometimes you may want to do more with the output data, especially how it is rendered. For example, perhaps you would like a time to be rendered on an image of a clock? Or a country code to be rendered as a flag? Or delve some further information from the information provided, such as a wordcount on text content? A kind of internationalization can be done using tags, on the basis that depending on the user, a Spanish text has been requested, not Danish…
Refs
Builtin tags. The most evident of these are the structuring tags like ‘for’ and ’if’. But there are also tags to, for example, turn a boolean into the text ‘yes’/‘no’,
https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#cycle
If you want to do something clever with images, or your own formatting, you can write your own tags,
https://docs.djangoproject.com/en/3.2/howto/custom-template-tags/
CSS and JavaScript
CSS is the classic way of modifying the look of a webpage. Mostly, unlike tags, CSS can’t modify the content of what is rendered. But it can transform the look, and is reusable and portable.
As for JS (JavaScript), I suppose most people would say it makes all things possible, Javascript is at it’s most intricate in sourcing new information from the web, or pushing given information to a server.
CDN or not
Or, Content Delivery Network. What I mean is, you can download large, generic lumps of code through the web, not by delivering them from a website server. This is not the place to fully explore CDN, but I’ll note that for stock CSS and JS components you may wish to use a CDN. A CDN is likely about twice the speed of your Django instance server, will not cost anything (not for stock CSS and JS), and is probably more reliably served across multiple points of delivery. That said, for CSS and JS, serving may only be a small part of serve times (images far outweigh minimal CSS serves) and CSS/JS files delivered through the server can be tuned to your own wishes. So there are arguments both ways.
Add local CSS/JS
To include the base code in a webpage (and ignoring the complexities of Javascript triggering and effect), you need the files of code. Place these files in two folders ‘sitename/static/css’ and/or ‘sitename/static/css’,
Add links to CSS/JS in templates like this. Note assuming ‘static’, see previous steps,