Should I render every page through a view function? - python

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.

Related

Why function-based views and class-based views?

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.

How do I reverse a named Django URL to the urlpattern that defines it?

My Django app contains a couple of external references, e.g. to the application's blog, which is not part of the Django codebase and is hosted on a different subdomain.
So far, links to these were spread all around the source code as direct absolute URLs.
Now I was wondering if there was a way to use Django's excellent URL routing system for these external URLs as well. I thought I could define them like this:
url(r'^permalink/blog/$', RedirectView.as_view(url='https://blog.example.com'), name='blog'),
Then I could just reference them as {% url 'blog' %} in my templates. That works.
Now I was wondering if there was a way to resolve these directly to the 'final' URL with a special (self-defined) template tag, so that they appear as https://blog.example.com to the user, as opposed to /permalink/blog/ (to the browser) or https://app.example.com/permalink/blog/ (to the user). I do already have a self-defined {% absolute_url %} template tag, which I use in templates that require absolute URLs, like transactional email.
However, I couldn't find a way to reverse a named URL (like external:blog) to its urlpattern as opposed to its final relative URL. To do this myself, it seems like I'd have to duplicate all the code from URLNode.render(), plus urlresolvers.reverse plus probably parts of RegexURLResolver._reverse_with_prefix(). That's quite a bunch of code, but I didn't see a simpler entry point/hook into the system. Did I miss a trick there?
To summarize, I'm basically looking for a function that I can pass a named URL to, e.g.
external:blog
and get a RegexURLPattern instance back, e.g.
RegexURLPattern(r'^permalink/blog/$', RedirectView('https://blog.example.com'), {}, 'blog')
or maybe just the view might work, too.

Django: Menu Controller

I have a question regarding Django. I created a site and everything works as it is indented to work. The only problem I have is that first of all my urls.py and views.py files are getting quite bloated (I have one method for every page I have) and that i have for every site one template. I use {% extend basetemplate.html %} for making it at least a bit generic. However I find this attempt not really nice. Creating a method inside the urls.py and views.py in addition to create a template html file seems the wrong attempt.
I already thought about building a big controller and did some googleing but i could not find what i was looking for.
Is there something like a best practice to achieve that? How do you guys handle the amount of templates?
Any advice would be more than welcome :)
One solution is to refactor your one application into multiple applications inside your project. Each would have its own urls.py & views.py.
If all your view does is render a template, then you can use TemplateView directly in your urls.py, and you don't need to define a view for each url.
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
url(r'^about/', TemplateView.as_view(template_name="about.html"), name="about"),
url(r'^contact/', TemplateView.as_view(template_name="contact.html"), name="contact"),
]
Other generic class based views might be useful as well. If there was a way to map the urls to the template names programatically (e.g. the template name was <slug>.html, you might not even need a url for each template. However, as I said in the comments above, I can't make any specific suggestions without seeing more of your code.
Create a directory called views with the following structure.
.../project/views/
.../project/views/__init__.py
.../project/views/feature_one.py
.../project/views/feature_two.py
.../project/views/feature_three.py
# in .../project/views/__init__.py import the others
from .feature_one import *
from .feature_tow import *
from .feature_threee import *
Now you can go on and import like before from your views. You can do the same thing for admin, models, form ..etc.
For templates, break them up, use inclusion tag to include the smaller partial files. Group them and create a nice directory structure.

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).

Using external URLs in Django's TEMPLATE_DIRS

Django's TEMPLATE_DIRS in Settings.py calls for unix style slashes.
Because of this, when I call
get_template('some/template.html')
in a view, the result always starts at the root, and results in a call to
/home/username/projectname/public/some/template.html
The problem is that I'd like to use templates hosted on an entirely different site. This works fine for other Settings.py fields (MEDIA_URL and STATIC_URL), where it will take an absolute http path with no objection.
Given an http path,
TEMPLATE_DIRS ('http://example.com/',)
in Settings.py will force
get_template('some/template.html')
in a view to try and find
/home/username/projectname/public/http://example.com/some/template.html
I've tried to circumvent this like so
TEMPLATE_DIRS ('../../../../http://example.com/',)
But it still forces a leading slash, so I get "/http://example.com", which is useless.
My questions:
Is there a way to trick this into pulling the template files from
another server?
Is that even feasible, given that the template files need to be
processed for the view?
Is it possible to create an alternate to 'django.template.loaders.filesystem.Loader' that doesn't call for unix style slashes?
You don't need to use the template directory is you dont want to. If you have a server that is serving template files, you can simply fetch them remotely using urllib2 and create and render the template with a context manually:
import urllib2
from django.template import Context, Template
tpl_html = urllib2.urlopen("http://mysite.com")
tpl = Template(tpl_html)
return tpl.render(Context({
'some_variable' : 'some_val',
})
If you are going to do this, you have to incorporate some caching, as for every request to using this template, you need to make an external request. Alternatively you could write this into a custom loader but it will suffer the same limitations.
You can't do this.
It has nothing to do with path names. It's just that the filesystem template loader needs to load things from the filesystem, hence the name.
This is completely different from the case of MEDIA_URL: that simply adds a path into your HTML, which your browser then loads. Django doesn't care where that file lives: although in fact the opposite applies, in that if you pass it a filepath that isn't a URL (ie served by a webserver somewhere), it simply won't work.
Now, you could write a template loader that gets its templates from another server. Template loaders are pluggable - you just need to put the name of your new loader in the TEMPLATE_LOADERS setting. The loader itself would need to use something like urllib.urlopen to get the template from the external server.
But think very carefully before you do this. This means that every single template request now requires a call to an external server before you can serve the page. In the typical case of a template that extends other templates and includes calls to included template tags, that might be five or ten calls. And, unlike media files, it can't be done in parallel: the page simply won't be served until the whole process is finished. This is likely to make your webserver very very slow.
I don't know why you think you need to do this. Templates are part of your application code, so they would normally live on the same server as your Python code. If you really have some reason to keep them externally, one solution might be to mount the external filesystem onto your webserver via something like sshfs. It's still likely to be very slow though. Think again.
No - it's not possible to trick it into pulling files from another server via http
Yes - you certainly could subclass django.template.loaders.filesystem.Loader (and by altering the load_template_source method appropriately) so that you could load templates via http
Once you had done 3 then the answer to 2 would be yes - it would be feasible - ultimately Django's template language doesn't care where it gets the file from, as long it's in the right format.
However, it seems like a very inefficient way of loading templates and more likely there is a much better way of achieving the same result.

Categories

Resources