10. Complex View information
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 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. 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,
For definitive answers, you’ll need to grit your teeth and dig into source.
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. You can tag in near any data. The data can be imported from anywhere, filtered by whatever method you choose, formatted however you wish. Filtering can be by other data that comes from the URL. URL data arrives in the kwargs. In a Generic View, the object also is available in 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/
Reacting to URLs
So far, we have used Django generic views to react to URLs. The views 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, here are some example paths, and you want the grab the last part of these paths, then look at it? You have URLs like,
How to get information information from the URL about color?
Simple View
This follows the two example URLs above exactly. In urls.py, use URL paths with ‘path converters’. The format is ‘<type:name>’. I can’t be bothered listing path converters—there’s a handful of them—if this interests you, go look at Django documentation. I added defaults to the paths 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 matched path section as a parameter (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
But the above isn’t the sophisticated way to do this. In truth, I find nothing wrong with a URL path match—it’s basic URL work. But assumes a defined enumeration of colors. It may be that the web‐user is submitting any of a wide range of color and, probably more important, the web‐app is intended to respond in some way to any color (even if it rejects it). The URL form for that is different,
The paths after the question marks are called a ‘query’. Note: no end slashes. Not needed.
Simple View
Right, well, every major web‐handling code has a way of dealing with queries. Java has great lumps of classes called ‘HTTPRequest’ and ‘HTTPResponse’, and query data is attached to them. So, I recall, though you never see them, has PHP. Django has too. This is kind of important—Django gathers query parameters automatically, so you should never try to match them. URL paths for a query look like,
The query data is passed in the request. It’s on an sub‐object of the request called GET (yes, there’s also a sub‐object called POST),
Generic View
Let’s disregard questions, drive forwards. For a Generic View the URL path 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 anyhow,
You can test for key existence,
And, yes, there is a similar object on request.POST.
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, to respond to a query URL 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