Best practice for Django components - django

Django provides a means of collecting assets into its Widget framework, and in turn using a form to present it, but how about doing this outside the forms framework?
For example, let's say I just want a simple, self-enclosed web component that requires two .js files, a CSS file, a template, and is backed by a view to generate some data. This isn't a "form" because it's not intended to collect input. Rather, assume it's, say, a customized scrollbar. I can't seem to find the right match for this usage pattern even though it seems common and straight-forward.
To do this now seems to mean adding the CSS to the top-level template; the JS to the template (or script tags arbitrarily in the included document); and then rendering the form as an include. But wouldn't it be easier to have something like:
class ScrollBar(...):
template_name = ...
class Assets:
...
and then rendering it via a templatetag, but with the ability for a context processor or other hook to extract the assets into their appropriate places in the page?
Something like:
index.html:
<html>
<head>
...
{% compressed_css %}
</head>
<body>
...
{% compressed_js %}
{% block content %}
{% endblock %}
</body>
scrollbar-using-page.html
{% extends "index" %}
{% block content %}
{% scrollbar args %}
{% endblock %}
with the end result being the scrollbar's template is rendered with the specified args, and its JS and CSS are merged into the compressed_css and compressed_js areas, respectively, above?
I think we get there almost 100% via this approach, without the compressed_js/compressed_css sections, which raises the question of whether then we just included these in all shared pages. (Alternatively, we could use nested/inherited blocks.)
Adam

Related

Django: how to set up the site name and show it at the end of all pages title

For example, there are 3 html templates with different titles:
<title>Page1</title>
<title>Page2</title>
<title>Page3</title>
How to append all the titles with the site name at the end using variable (or other ways)?:
<title>Page1 - {{Here is the configurable Site Name}}</title>
<title>Page2 - {{Here is the configurable Site Name}}</title>
<title>Page3 - {{Here is the configurable Site Name}}</title>
You normally do this by setting the site name in a base template that you then extend from your other templates.
Suppose you have this base.html template
<html>
<head>
<title>{% block page-title %}{% endblock %} - My Site</title>
</head>
...
You can then extend this template from your other pages:
{% extends "base.html" %}
{% block page-title %}My first page{% endblock %}
...
This solution is what is normally seen in many Django projects.
Now if you want to make the site name configurable, from your Django settings for example, you'll need a way to pass it along to your view for rendering. Since this is something you'll be doing for every view, it's better to do this in context processor so you don't have to do it manually.

Django nested templates

In trying to keep with DRY, I'm setting up my Django project HTML files now. I have successfully extracted most repeated information to my base.html page. On most (but not all) of my pages, my content is displayed within a general 'panel' which is basically just a container set-up with styling, but it's got a few div-tags to it so it looks a bit ugly and I'm having to type out the exact same code out several times on each page.
My idea was to extract this to a 'panel.html' then call it whenever I need it, for example some pages might just have one 'panel' whereas my dashboard (it's an administrative site) will have maybe 15+. So it seemed a better idea and cleaner to not have to type out all this code each time I need to set up a 'panel'.
My ideal page would look something like..
{% extends 'base.html' %}
{% block content %}
{% extends 'panel.html' %}
{% block panel_content %}
Panel content...
{% endblock panel_content %}
{% extends 'panel.html' %}
{% block panel_content %}
Second panel content
{% endblock panel_content %}
{% endblock content %}
I know I can't use extends multiple times but I'm using it just as an example for what it is I'm trying to achieve.
I am going to potentially have hundreds of these identical 'panels' across my site but each containing different content and it would be so much cleaner if I could just have one stored somewhere in a HTML file and call it however many times I need.
Is there a way to do this?
You can use include
{% include "panel.html" %}
I should mention that too many include statements create a performance issue.

Django asset manager for Views or template tags?

I come to Django having used the Yii2 PHP framework. One of the good features about that is it allows you to create asset files for CSS and JS which are then loaded into the base layout file at runtime. This allows you to keep the base template clean of CSS and JS markup within the head and at the bottom of the HTML document. The CSS and JS files you specify in the asset file are automatically placed in the correct position in the document and you can also specify dependencies if needed.
At the moment, with Django I am having to edit the base.html file manually which is not ideal.
I know you can use the Media class for forms, and in admin.py, which does a similar job. However, what I would like to do is to something like this (for example) in inclusion template tags or in a class based view perhaps.
Is this possible?
Many thanks!
UPDATE
Here is a similar question Is it possible to use django's custom template tags to insert code in other blocks in the template?
do you find block tag?
base.html
<head>
{% block extra_css %}{% endblock %}
<head>
view.html
{% extends 'base.html' %}
{% block extra_css %}
<link rel="stylesheet" href="YOUR URL">
{% endblock %}

Django how to dynamically add js and CSS in sub templates?

I am new to Django.
I have a basic template set up where I have base.html using {% block body %}{% endblock %} to include a sub template of index.html and test.html where they have {% extends 'base.html' %} at the top.
The base.html template includes Bootstrap. It is where the CSS and JS are included. index.html needs to include select2 but test.html does not.
I could use blocks here to solve my problem (adding CSS and JS block to base.html) but I see that as getting very messy very quickly.
Is there anyway I can use assets in Django to create a select2 asset and have that called in the sub template to register the needed JS and CSS with the parent template?
All I see is compression and numerous searches have, so far, come up empty.
It okay to add 2 more blocks in your base.html:
<some css>
{% block additional_css %}
{% endblock additional_css %}
...
<some js>
{% block additional_js %}
{% endblock additional_js %}
and the override them in any page extended from base.html:
{% extends "base.html" %}
{% block additional_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap-datetimepicker.min.css' %}">
{% endblock additional_css %}
...
{% block additional_js %}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.0/moment.min.js"></script>
<script type="text/javascript" src="{% static 'js/bootstrap-datetimepicker.min.js' %}"></script>
{% endblock additional_js %}
That is a good practice because in this case the scripts will load in the very end and if some of your added script require for example JQuery, you won't face any problems.
It doesn't make the code messy, it's flat and easy to explain. It's better to think how not to make JS messy, and as you pointed, there are several ways to do this, on of them is to compress all the JS.
There are a few options that I can think of
The first is the ugly way that involves an {% if include_my_js_please %} in the base.html that is ignored if the context variable isn't included and for obvious reasons, arguments would be had if this made its way into our production code
The second is the way that you say can get very messy but its the way we do it and works very well for us, we have an {% extended_head %} and {% extended_footer %} in the base.html and as you'd expect we use this sparingly when required. Although we are very careful about what is included into this.
The third way is to just include everything in the base.html and only worry about it when it actually becomes a problem (I can see both the pros and con's of this)
and the fourth and final way I can think of is to make use of the Forms Media class
Django allows you to associate different files – like stylesheets and scripts – with the forms and widgets that require those assets. For example, if you want to use a calendar to render DateFields, you can define a custom Calendar widget. This widget can then be associated with the CSS and JavaScript that is required to render the calendar. When the Calendar widget is used on a form, Django is able to identify the CSS and JavaScript files that are required, and provide the list of file names in a form suitable for easy inclusion on your Web page.
Obviously this doesn't work in all use cases

Django: Extends or Include?

My friend and I are having a small argument. In my current Django Project, I have created a file called menu.html which will contain a bunch of links configured and formatted into a list. Instead of manually hard-coding the menu into each page, I am currently including the menu using the following Django/Python code:
{% include 'menu.html' %}
However, my friend is suggesting that this is the incorrect way to do it. He said I need to use extends instead of include and then define content, something like this:
{% extend 'menu.html' %}
{% block content %}
The rest of my content here.
{% endblock %}
That's a bit of extra code. Does it really matter which I use? I would prefer to use the former.
Yes, it matters. First of all extends can only occur as the very first line of the file. Secondly, include pushes and pops a context object on the resolve stack, which means that value created in the context while in the include will go out of scope when it returns.
My rule is: create base.html template files that define the overall structure of your site and use liberal amounts of {% block foo %} around critical areas. Then all of your other templates extends the base (or something that itself extends the base) and you replace those blocks as needed.
include, on the other hand, is good for encapsulating things you may need to use in more than one place, maybe even on the same page.
Update:
I have been using my own library of template_tags for so long that I forget that Django's template language still has major gaps in functionality. The tag in question here is from an early django snippet called expr which I have heavily edited and extended. You can say, for example, {% expr 'Fred' as name %} (or any valid Python expression), and it will store the result in the 'name' slot in the current Context. If this occurs in an included template, name's value will be popped on exit from the template file.
You can sort of achieve this with the {% with %} tag, but expr gives me much greater flexibility, including doing arbitrarily complex calls. This originally came up when having to create complex cached objects that required expensive DBMS interactions that couldn't be done up in the view, they had to be invoked in the template itself.
Email me (in my profile) if you need to get deeper into this.
( his friend )
What I actually meant was defining a base.html so you can inherit a base template consistent of several generic sections, this one includes the doctype, html element defines 3 blocks for content and nav and optional area to override/insert script/link elements in the head.
<!doctype>
<html>
<head>
{%block extrahead %} {%endblock %}
</head>
{%block nav %}
<nav>
<ul>
<li>home</li>
</ul>
</nav>
<div id="content">
{% endblock %}
{%block content %}
{% endblock %}
</div>
</html>
Then you can define homepage.html:
{% extends "base.html" %}
{% block content %}
homepage content
{% endblock %}
homepage.html would then have the navigation because it extends base.html.
In this case placing the menu in base.html and extending from this seems to be more senseful.
including is great for splitting complex template and reusing those chunks.
let's say, you use the same list-style in different places of the site, but you send other queryset to it. as long, as you call the querysets the same, you only need to write the template code once.
Here I use differnt templates for normal- and ajax-requests. But using include let me re-use most parts in both templates