Skip to content

django template (view)

Basic

Django Template System Basic

A template tag is surrounded by {% and %}. This is because Django’s tags are so flexible. Some examples performed by template tags are as follows:

  1. Display Logic: E.g., {% if %} Add {% endif %}
  2. Loop Control: E.g., {% for x in y %}...{% endfor %}
  3. Block Declaration: E.g., {% block content %}...{% endblock %}
  4. Content Import: E.g., {% include “header​.ht​ml” %}
  5. Inheritance: E.g., {% extends “base​.ht​ml” %}

A template variable is surrounded by {{ and }}. These template variables are passed to the template at runtime in the Context.

  1. Simple Variables: E.g., {{ name }}
  2. Object Attributes: E.g., {{ page.heading }}
  3. Dictionary Lookups: E.g., {{ dict​.it​em }}
  4. List Indexes: E.g., {{ list_items.2 }}
  5. Method Calls: E.g., {{ var​.low​er }}, {{ mydict​.pu​sh }}
  • Display Logic - {% ... %} (for Statements )

    <h1>Favorite Color</h1>
    <ul>
        {% for user in colors %}
            <li>{{ user.color }}</li>
        {% endfor %}
    </ul>
    
  • If:

    In Jinja, it is easiest to use if as a variable that is defined and then returns some values, not empty and not false.

    {% if users %}
        <ul>
            {% for user in users %}
                <li>{{ user.username}}</li>
            {% endfor %}
        </ul>
    {% endif %}
    
  • If Expression:

    It is also used as an inline expression. For example, you can add this to extend your code logic.

    {% extends condition if the condition is defined else 'default​.ht​ml' %}
    

Mastering Django A Beginner’s Guide Edited by Sufyan bin Uzayr pg-124

Adding Templates

Adding Templates

The first thing to learn is where to put templates in a Django project. By default, Django's template loader looks inside each app for templates that go with it.

Now, let us create a templates folder.

mkdir templates

Next, we have to add the new template to the settings.py file inside the django project so that Django knows where our new templates directory is. Add the following to the TEMPLATES setting under "DIRS."

TEMPLATES = [
    {
        ...
        "DIRS": [BASE_DIR / "templates"],
        ...
    }
]

Book: Python Flask and Django by emenwa global

Example

We will use the built-in TemplateView to show our template in our view. Edit the views.py file.

from django.views.generic import TemplateView

class HomePageView(TemplateView):
    template_name = "home.html"

Since HomePageView is now a Python class, we had to capitalize it. Unlike functions, classes should always start with a capital letter. The logic for showing our template is already built into the TemplateView. All we need to do is tell it the name of the template.

from django.contrib import admin
from django.urls import path
from django.urls import include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("", include("page.urls")),
]

one big difference: when using Class-Based Views, you always add as view() to the end of the view name.

from django.urls import path
from .views import HomePageView

urlpatterns = [
    path("", HomePageView.as_view(), name="home"),
]

Extending Templates

The best thing about templates is how you can extend them. Most websites have headers or footers that you see on every page. How can you do that?

First, we make a file called base.html within the templates folder.

Info

<header>
    <a href="{% url 'home' %}">Home</a>
    <a href="{% url 'about' %}">About</a>
</header>

{% block content %}
{% endblock content %}
{% extends "base.html" %}

{% block content %}
    <h1>Welcome to my website</h1>
{% endblock content %}

Static dir

mkdir static

# to create a CSS subfolder:
mkdir static/css
# settings.py
STATIC_URL = "static/"

STATICFILES_DIRS = [BASE_DIR / "static"]

Advanced


Other Topic

Example

The difference between the two declarations lies in the method used to construct the path to the static directory:

1. Using the / Operator:

STATICFILES_DIRS = [
    BASE_DIR / "static"
]

This approach uses the / operator for path concatenation. However, this syntax is not standard in Python and may cause an error unless you have overridden the behavior of the / operator to handle path concatenation.

2. Using os.path.join():

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

This approach uses the os.path.join() function to construct the path to the static directory. It is the standard and recommended way to join path components in Python, ensuring compatibility across different operating systems.

In summary, the second declaration that uses os.path.join(BASE_DIR, 'static') is correct and standard. It ensures that the path is constructed correctly regardless of the operating system being used. The first declaration using the / operator may not work as expected and is not a common practice in Python for constructing paths.

static folder

Yes, that's correct. STATICFILES_DIRS and STATIC_ROOT serve different purposes, so they typically point to different directories.

1. STATICFILES_DIRS:

STATICFILES_DIRS is used during development to specify additional directories where Django should look for static files. These directories can contain static files that are not tied to specific apps or are shared across multiple apps. This setting allows you to include third-party static files, custom project-wide static files, or override static files provided by apps or libraries.

For example:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
    #   '/path/to/external/static/files/',
]

2. STATIC_ROOT:

STATIC_ROOT is used for deployment purposes. It specifies the directory where Django collects all the static files from your project during the deployment process. These collected static files are meant to be served directly by a web server like Nginx or Apache in a production environment.

For example:

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

After running collectstatic, Django gathers static files from both the app-specific static directories and the additional directories specified in STATICFILES_DIRS, and places them into the directory specified by STATIC_ROOT.

In summary, STATICFILES_DIRS and STATIC_ROOT should point to different directories. STATICFILES_DIRS is for specifying additional directories where Django should look for static files during development, while STATIC_ROOT is for specifying the directory where Django should collect all static files for deployment.


STATIC_URL is a setting in Django used to specify the base URL from which static files will be served. It defines the URL prefix to access static files in your web application.

By default, STATIC_URL is set to '/static/' in Django projects, but you can customize it to fit your application's requirements. For example, if you want to serve static files from a different URL or path, you can modify STATIC_URL accordingly in your project's settings.


Templates


Choosing Between Direct Slug Usage and Named URL Patterns in Django Templates

Both approaches have their advantages and use cases:

1. <a href="{{ blog.slug }}">{{ blog.title }}</a>:

  • This approach directly uses the value stored in the slug field of your BlogItem model to generate the URL.
  • It's simpler and more straightforward.
  • You don't need to define URL patterns or use the {% url %} template tag.
  • However, it's less flexible if you ever need to change the URL structure or if you want to handle URLs differently in different parts of your website.

2. <a href="{% url 'blog:inner' slug=blog.slug %}">{{ blog.title }}</a>:

  • This approach uses the {% url %} template tag to generate the URL based on the specified view name ('blog:inner') and the provided parameters (slug=blog.slug).
  • It's more flexible and maintainable. If you ever need to change the URL structure or if you want to reuse the same URL pattern in different parts of your website, you only need to update the URL pattern in your urls.py file.
  • It ensures consistency and helps prevent errors in URL generation.
  • However, it requires you to define URL patterns in your urls.py file and use the {% url %} template tag, which adds some complexity.

In general, if your URL structure is simple and unlikely to change, and if you don't need the flexibility provided by named URL patterns and the {% url %} template tag, you can use the first approach (<a href="{{ blog.slug }}">{{ blog.title }}</a>). Otherwise, if you want more flexibility and maintainability, especially for larger or more complex projects, the second approach (<a href="{% url 'blog:inner' slug=blog.slug %}">{{ blog.title }}</a>) is recommended.

Rendering HTML Content

To display content from a TinyMCE field in HTML, you can directly render the HTML content using the safe filter provided by Django templates. This filter ensures that the HTML content is rendered as HTML and not escaped as text. Here's how you can do it:

<div class="col-md-12">
    <p>{{ about.description | safe }}</p>
</div>

By using the safe filter, Django will render the HTML content stored in the description field without escaping it. Make sure to sanitize the HTML content before storing it in the database to prevent security vulnerabilities such as cross-site scripting (XSS) attacks. Django's safe filter does not perform any sanitization on the content; it merely marks it as safe for rendering.

active in navigation website

Tip

To change the active state of the navigation links based on the current page, you can use the request.path in your template to compare it with the URL of each navigation link. Here's how you can do it:

<ul class="navbar-nav mb-2 mb-lg-0">
    <li class="nav-item {% if request.path == '/' %}active{% endif %}">
        <a class="nav-link" href="{% url 'home' %}">Home</a>
    </li>
    <li class="nav-item {% if request.path == '/about/' %}active{% endif %}">
        <a class="nav-link" href="{% url 'about' %}">About</a>
    </li>
    <li class="nav-item {% if request.path == '/service/' %}active{% endif %}">
        <a class="nav-link" href="{% url 'service' %}">Service</a>
    </li>
    <li class="nav-item {% if request.path == '/project/' %}active{% endif %}">
        <a class="nav-link" href="{% url 'project' %}">Project</a>
    </li>
    <li class="nav-item {% if request.path == '/blog/' %}active{% endif %}">
        <a class="nav-link" href="{% url 'blog:blog' %}">Blog</a>
    </li>
    <li class="nav-item {% if request.path == '/contact/' %}active{% endif %}">
        <a class="nav-link" href="{% url 'contact' %}">Contact</a>
    </li>
</ul>

In this example:

  • {% if request.path == '/' %} checks if the current page is the home page. If it is, it adds the active class to the corresponding <li> element.
  • Similarly, you can check the request.path against each URL and add the active class accordingly.

Make sure that request is available in your template context. In Django, request is typically available by default in the template context if you've enabled the django.template.context_processors.request context processor in your settings. If not, you need to pass request explicitly to your template context.

To highlight the "Blog" navigation item when you're on a blog item page, you need to modify the logic to check if the current page URL contains /blog/. Here's how you can do it:

<ul class="navbar-nav mb-2 mb-lg-0">
    <li class="nav-item {% if '/blog/' in request.path %}active{% endif %}">
        <a class="nav-link" href="{% url 'blog:blog' %}">Blog</a>
    </li>
    <!-- Add other navigation items -->
</ul>

In this modification:

  • {% if '/blog/' in request.path %} checks if the current page URL contains /blog/. If it does, it adds the active class to the corresponding <li> element.
  • By using in, we're checking if /blog/ is part of the current URL. This way, any URL that includes /blog/, like /blog/ktm-bazar, /blog/some-other-blog-post, etc., will highlight the "Blog" navigation item.

Make sure that request is available in your template context as explained in the previous response. If not, ensure that you pass request explicitly to your template context in your views.



templates

Argument Outputs
openblock {%
closeblock %}
openvariable {{
closevariable }}
openbrace {
closebrace }
opencomment {#
closecomment #}

url template tag

Yes, that's correct. When using the {% url %} template tag in Django templates, you specify the name of the URL pattern, not the name of the view function or class-based view.

The name parameter you provide in the URL pattern definition (name='...') is what you use to refer to that URL pattern in the {% url %} template tag.

Here's an example to clarify:

urls.py
from django.urls import path
from .views import my_view_function, MyViewClass

urlpatterns = [
    path('home/', my_view_function, name='home_view_function'),  # Function-Based View
    path('about/', MyViewClass.as_view(), name='about_view_class'),  # Class-Based View
]

In the above urls.py example:

  • home_view_function is the name of the URL pattern associated with the function-based view my_view_function.
  • about_view_class is the name of the URL pattern associated with the class-based view MyViewClass.

Now, when referencing these URL patterns in your templates using the {% url %} template tag, you would use their respective names:

html
<a href="{% url 'home_view_function' %}">Link to Home (Function)</a>
<a href="{% url 'about_view_class' %}">Link to About (Class)</a>

So, you specify the name of the URL pattern, not the name of the view function or class-based view.


Reference