Why function-based views and class-based views? - python

I'm a beginner to web development in django, and I'm wondering why views needed to be rendered with functions and classes? Can't the urls module just link the url to the HTML template directly rather than indirectly through a function-based view?

You can indeed have the urls module just render the HTML for you right way. For that, you can use direct_to_template: https://django.readthedocs.io/en/1.4.X/topics/generic-views.html#using-generic-views
You would rely on a function when you have any extra processing to be done before sending the response ("rendered template") to the user. You could need to log the user's IP address, for example, or you could load data from a database to fill in the template. Or you can not even have to render a HTML, but a JSON instead. That's why you would need a custom view, which would be implemented in either a function or class.

So the point of Django in general is you're going to want to be serving more than just static HTML, you'll probably want to process that in some way. As other answers have said, if you just want to return HTML, you can use a TemplateView (https://docs.djangoproject.com/en/3.0/ref/class-based-views/base/#templateview) or just have your web server server the static files (https://docs.djangoproject.com/en/3.0/howto/static-files/deployment/)
Unless your use case is a single page app, its highly likely you'll have some HTML that's common to multiple pages, in which case you can include and extend templates.

Related

Django - beginner- what is the process for passing information to a view via a url?

I am working on my first django project which is also my first backend project. In the tutorials/reading I have completed, I haven't come across passing information back to django without a modelform.
My intention is to calculate a value on a page using javascript and pass it to django when a user hits a submit button on that page. The submit button will also be a link to another page. I know I could process the information in a view via the url if I knew how to pass the information back to django.
I'm aware that django uses MVC and as I have my models and views in place, I am lead to believe that this has something to do with controllers.
Basically, I would like to know how to pass information from a page to django as a user follows a link to another page. I understand that this isn't the place for long step by step tutorials on specific topics but I would appreciate any links to resources on this subject. I don't know what this process is even called so I can't search documentation for it.
EDIT:
From further reading, I think that I want to be using the submit button to GET or POST the value. In this particular case, POST is probably better. Could someone confirm that this is true?
Yes, generally POST is a better way of submitting data than GET. There is a bit of a confusion about terminology in Django. While Django is, indeed MVC, models are models, but views are in fact controllers and views are templates. Since you are going to use AJAX to submit and retrieve the data, you don't care about templates. So what you most likely want is something like this
in your urls.py as part of your urlpatterns variable
url(r'mything/$', MyView.as_view())
in your views.py
from django.views import View
from django.http import HttpResponse
class MyView(View):
def post(self, request):
data = request.POST
... do your thing ...
return HttpResponse(results)
and in your javascript
jQuery.post('/mything/', data, function() { whatever you do here })
There're many ways, you can achieve this in django. Following are the two ways, that I generally prefer :-
1) As a query string parameter in the URL
eg. http://localhost/getPatientInfo?patientId=23&name=Sachin
2) Making URL dynamic, to include the information in the view itself.
eg. http://localhost/patientInfo/23/Sachin
In case 1:-
You will have to do,
patientId = request.GET["patientId"]
name = request.GET["patientName"]
In case 2:
Your URL conf will be something like :
urls = [
url("^patientInfo/(\d+)/([^/]+)$", yourViewFunc)
]
And in your view func :-
def yourViewFunc(request, patientId, patientName):
# your logic goes here
pass
For info. related to URLConf, refer to https://docs.djangoproject.com/en/1.10/topics/http/urls/#example

Implementing Universal Search in a Django Application

We have a large Django application made up of a large number of different views (some of which contain forms). As with most large applications, we use a base layout template that contains the common layout elements across the applications (mainly a header and a footer), which the templates for all of our views extend.
What we are looking to do is create a universal search box in our application, accessible on every page, which allows users to perform searches across the entire application, and want to place the search box inside the header, which involves placing a form inside our base layout template. This means that every view in our application will need to be able to handle the submission of this search form. Once this search form is submitted, we will need to redirect the user to another view containing the search results.
However, we are struggling to come up with a pattern to handle this. Does anyone know of functionality built into Django that will help us to build this? Failing that, can anyone suggest a good strategy for modifying our application so that we can handle this use-case without having to modify a large number of existing views (which we don't have the resources to do at the moment)?
Please note that the focus of this question is intended to be the best way to handle the submission of a form which appears in every view, and not strategies for implementing a universal search algorithm (which we have already figured out).
Ideas Explored So Far
Our first idea was to create a base View class that implements handling the universal search form submission, and have each of our views extend this. However, this is not possible because we already have views that inherit from a number of different Django view classes (TemplateView, ListView, FormView and DeleteView being some examples), and to be able to build our own common view class would mean either writing our own version of these Django view classes to inherit from our own view base class, or re-writing a large number of our views so they don't use the Django view classes.
Our next idea was to implement a mixin that would handle the universal search form submission, in an attempt to add this functionality to all our views in a way that allows us to continue using the different Django view classes. However, this brought to light two new problems: (a) how could we do this without modifying each of our views to become a form view, and (b) how can we do this in a way that allows the form handling logic to play nicely when mixed in to existing FormViews?
This seems like such an obvious question that maybe I'm overlooking something. But as others have said your universal search form should not make a POST request to the view that rendered the current page.
Each html form has an action attribute. The attribute of your search form should point towards an URL. Probably something like /search. That url would have a view behind it that handled the POST request from the form and returned the search results. Django has URL template tags to make this easy. {% url 'myapp.views.search' %} will give you the correct url for the search view function if it lived inside the views module in myapp. So the relevant bit of html in your base template would be something like:
<form action="{% url 'myapp.views.search' %}">
<input type="text" name="qs" placeholder="Search">
</form>
If you are planning on displaying the search results on a new page there is absolutely no need to return JSON or anything like that. Just have a search view that looks like this
def search(request):
query = request.POST.get('qs', '')
results = SomeModel.objects.filter(name=query) # Your search algo goes here
return render(request, 'search_results.html', dict(results=results))
Instead of handling the form submission on every view of the application, you can implement a separate view (endpoint), which handles all the search queries. (an endpoint which returns JSON result) since you dont want to add overhead of rendering the whole page with that view. So the search query (which client side AJAX performs to the webserver) will return JSON response, and the Javascript can render that response. This way you can keep the search view isolated from the rest of the views. (Django REST will be helpful in this case)
And this search form will be included in your base template, so your search box is accessible from the entire application, and it submits to the same view. And the AJAX function will handle the server response for rendering it.
It seems like you just need to create another SearchView which takes the query and displays the results. I am not sure if the results have to be displayed differently depending on which page the search has been performed from but it does not seem like.
The form would not have anything to do with the other views. You could just hard code it in the base template.

Add custom Django admin action

I'm looking for ways of adding custom actions to a Django admin change page. I am not looking for actions that can be added to the dropdown box in the overview.
One model in my Django application contains information about documents, and those are automatically compiled to PDF files at the frontend. I'd like to give the administrator the possibility to quickly render the PDF directly from the change page to be able to quickly check the results.
I've already played around with overriding change_form.html/submit_line.html, and it's absolutely no problem to add a button. But I wonder how to extend the admin module in a clean way so that it includes my custom action.
Since custom admin views are basically just normal views there aren't many specialities. A few things you should consider for a cleaner integration:
Add the url pattern through get_urls() of the AdminSite.
Provide the current_app argument to RequestContext or Context when rendering a template which subclasses admin templates.
EDIT:
Found a an example here:
http://shrenikp.webs.com/apps/blog/show/5211522-add-custom-view-method-for-django-admin-model-
Note, that the example doesn't utilize the current_app argument i've mentioned. I suppose your view to generate the PDF just returns a HttpResponse with the appropriate content type rather than rendering a response with a Context, so it's not needed. All in all the current_app only makes sense when you subclass an admin template used by your custom view which actually makes use of current_app somewhere.
The example encapsulates the urls and view in a ModelAdmin. It is also possible to do this through a AdminSite subclass, but at least in your use case this is probably overkill.
By the way, overriding the change_form.html template for your app to add a button to the standard change view is just fine. There is no special api for this in the admin (unfortunately).

Should I render every page through a view function?

I have a simple static page that displays some information about the website. should i render this page via a render_to_response() even though it is static or should i simply display it as a normal html file?
the only thing I am concerned about is adding excess load on the server.
If you are worrying about server load, you should set up a proxy like squid or varnish. The proxy can cache the static content so your server will only get a more one request every time the cache expires
You might want to check out Hyde, which uses Django and specializes in static content.
It doesn't sound like you're really talking about "static content" in the way Django developers usually do (Javascript, CSS, images, etc.).
You say you need Django templates, but imply the content on those pages doesn't need to be changed. This sounds like the perfect opportunity for the built-in Django TemplateView (example urls.py from the docs):
from django.views.generic import TemplateView
urlpatterns = patterns('',
(r'^about/', TemplateView.as_view(template_name="about.html")),
)
As gnibbler says, if you're very worried about performance then some kind of cache — Django actually has caching built-in,
and you can enable it for specific views with the #cache_page decorator.

URLs stored in database for Django site

I've produced a few Django sites but up until now I have been mapping individual views and URLs in urls.py.
Now I've tried to create a small custom CMS but I'm having trouble with the URLs. I have a database table (SQLite3) which contains code for the pages like a column for header, one for right menu, one for content.... so on, so on. I also have a column for the URL. How do I get Django to call the information in the database table from the URL stored in the column rather than having to code a view and the URL for every page (which obviously defeats the purpose of a CMS)?
If someone can just point me at the right part of the docs or a site which explains this it would help a lot.
Thanks all.
You dont have to to it in the flatpage-way
For models, that should be addressable, I do this:
In urls.py I have a url-mapping like
url(r'(?P<slug>[a-z1-3_]{1,})/$','cms.views.category_view', name="category-view")
in this case the regular expression (?P<slug>[a-z1-3_]{1,}) will return a variable called slug and send it to my view cms.views.category_view. In that view I query like this:
#render_to('category.html')
def category_view(request, slug):
return {'cat':Category.objects.get(slug=slug)}
(Note: I am using the annoying-decorator render_to – it is the same as render_to_response, just shorter)
Edit This should be covered by the tutorial. Here you find the url-configuration and dispatching in every detail. The djangobook also covers it. And check pythons regex module.
Of course you can use this code.
Your question is a little bit twisted, but I think what you're asking for is something similar to how django.contrib.flatpages handles this. Basically it uses middleware to catch the 404 error and then looks to see if any of the flatpages have a URL field that matches.
We did this on one site where all of the URLs were made "search engine friendly". We overrode the save() method, munged the title into this_is_the_title.html (or whatever) and then stored that in a separate table that had a URL => object class/id mapping.ng (this means it is listed before flatpages in the middleware list).

Categories

Resources