DEV Community

Ashutosh Krishna
Ashutosh Krishna

Posted on • Originally published at iread.ga on

Grocery Bag using Django (Part-2) - Fixing Templates and Static Files

Introduction

Image description

In the last part, we had set up our GroceryBag project. In this part, we will fix our templates and static files URLs in the templates. The problem is, if you look at the templates, the code is similar in all of the files. We can fix this problem using Template Inheritance. Inheritance means to get something from another, i.e. the child(one which is inheriting) gets the properties from its parent(one which is being inherited). We use Template Inheritance to avoid writing the same HTML code again and again in various files.

The next thing we are going to fix is the way we are linking the static files with these templates. Let's fix this problem first, then we'll move to Template Inheritance.

Fixing Static Files URLs

Until now, we're linking the static files(CSS, Images, and JavaScript) with the templates in this way:

<link rel="stylesheet" href="css/style.css" />
Enter fullscreen mode Exit fullscreen mode

But this won't be working if you have put the template files and static files in their respective directories correctly. If you remember, in the previous blog, we had added STATIC_URL and STATICFILES_DIR in our GroceryBag/settings.py as this one:

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    BASE_DIR / "static",
]
Enter fullscreen mode Exit fullscreen mode

With these configurations in place, we are ready to serve the static files dynamically in the templates using this syntax:

{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}" />
Enter fullscreen mode Exit fullscreen mode

You can learn more about these in the official documentation of Django.

Django Template Inheritance

As we know, we use Template Inheritance to avoid writing the same HTML code again and again in various files. Suppose, you have a few things that are common in all the web pages. What we can do is, instead of writing the code, again and again, we can write the common code in a base.html file and then extend this file in other HTML templates.

extends and block tags

The extends tag is used to inherit a parent or base template inside a child template. The syntax looks like this:

{% extends "filename.html" %}
Enter fullscreen mode Exit fullscreen mode

The filename should be the path of the base template within the templates directory.

The block tag is used to override some parts of the parent template in the child template. We can create as many blocks as we need. The syntax looks like this:

{% block block_name %}

{% endblock block_name %}
Enter fullscreen mode Exit fullscreen mode

Example

Suppose we have a base template base.html as this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{% block title %}{% endblock title %} | Grocery Bag</title>
  </head>
  {% block content %} {% endblock content %}
</html>

Enter fullscreen mode Exit fullscreen mode

We can inherit this base template and create a child template index.html as this:

{% extends "base.html" %}

{% block title %}Index Page{% endblock title %} 

{% block content %}
<body>
  Hello World!
</body>
{% endblock content %}

Enter fullscreen mode Exit fullscreen mode

Fixing our templates

Now that we have learned Template Inheritance, we can create a base.html file in the templates directory and add the following content inside it:

{% load static %}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>{% block title %}{% endblock title %} | Grocery Bag</title>
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />
<!-- JavaScript Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="{% static 'css/style.css' %}" />
    {% block custom_head %} {% endblock custom_head %}
  </head>
  {% block content %} {% endblock content %}
</html>

Enter fullscreen mode Exit fullscreen mode

Notice how we linked the CSS file to the webpage. We have also created three blocks - title, custom_head and content. title will be used to supply the title from each page, custom_head will be used to add more static files required by other web pages, and content will be used to supply the body.

Now, let's fix the other webpages.

index.html

{% extends "base.html" %}{% load static %} {% block title %}View Bag{% endblock title %} 

{% block content %}
<body>
  <div class="container mt-5">
    <!-- top -->
    <div class="row">
      <div class="col-lg-6">
        <h1>View Grocery List</h1>
      </div>
      <div class="col-lg-6 float-right">
        <div class="row">
          <div class="col-lg-8">
            <!-- Date Filtering-->
            <input type="date" class="form-control" />
          </div>
          <div class="col-lg-4">
            <input type="submit" class="btn btn-danger" value="filter" />
          </div>
        </div>
      </div>
    </div>
    <!-- // top -->
    <!-- Grocery Cards -->
    <div class="row mt-4">
      <!--- -->
      <!-- Loop This -->
      <div class="col-lg-4">
        <div class="card">
          <div class="card-body">
            <h5 class="card-title">Tomato</h5>
            <h6 class="card-subtitle mb-2 text-muted">2 Pcs.</h6>
            <p class="text-success">BOUGHT</p>
          </div>
        </div>
      </div>
      <!-- // Loop -->
      <div class="col-lg-4">
        <div class="card">
          <div class="card-body">
            <h5 class="card-title">Chicken</h5>
            <h6 class="card-subtitle mb-2 text-muted">2Kgs</h6>
            <p class="text-danger">NOT AVAILABLE</p>
          </div>
        </div>
      </div>

      <div class="col-lg-4">
        <div class="card">
          <div class="card-body">
            <h5 class="card-title">Posto</h5>
            <h6 class="card-subtitle mb-2 text-muted">50gms</h6>
            <p class="text-info">PENDING</p>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
{% endblock content %}

Enter fullscreen mode Exit fullscreen mode

add.html

{% extends "base.html" %}{% load static %} {% block title %}Add to bag{% endblock title %} 

{% block content %}
<body>
  <div class="container mt-5">
    <h1>Add to Grocery Bag</h1>
    <form>
      <div class="form-group mt-2">
        <label>Item name</label>
        <input type="text" class="form-control" placeholder="Item name" />
      </div>
      <div class="form-group mt-2">
        <label>Item quantity</label>
        <input type="text" class="form-control" placeholder="Item quantity" />
      </div>
      <div class="form-group mt-2">
        <label>Item status</label>
        <select class="form-control">
          <option value="0">PENDING</option>
          <option value="1">BOUGHT</option>
          <option value="0">NOT AVAILABLE</option>
        </select>
      </div>
      <div class="form-group mt-2">
        <label>Date</label>
        <input type="date" class="form-control" placeholder="Date" />
      </div>
      <div class="form-group mt-2">
        <input type="submit" value="Add" class="btn btn-danger" />
      </div>
    </form>
  </div>
</body>
{% endblock content %}

Enter fullscreen mode Exit fullscreen mode

update.html

{% extends "base.html" %}{% load static %} {% block title %}Update bag{% endblock title %} 

{% block content %}
<body>
  <div class="container mt-5">
    <h1>Update Grocery Bag</h1>
    <form>
      <div class="form-group mt-2">
        <label>Item name</label>
        <input
          type="text"
          class="form-control"
          placeholder="Item name"
          value="TOMATO"
        />
      </div>
      <div class="form-group mt-2">
        <label>Item quantity</label>
        <input
          type="text"
          class="form-control"
          placeholder="Item quantity"
          value="2PCS"
        />
      </div>
      <div class="form-group mt-2">
        <label>Item status</label>
        <select class="form-control">
          <option value="0">PENDING</option>
          <option value="1" selected>BOUGHT</option>
          <option value="0">NOT AVAILABLE</option>
        </select>
      </div>
      <div class="form-group mt-2">
        <label>Date</label>
        <input
          type="date"
          class="form-control"
          placeholder="Date"
          value="2020-03-20"
        />
      </div>
      <div class="form-group mt-2">
        <input type="submit" value="Update" class="btn btn-danger" />
      </div>
    </form>
  </div>
</body>
{% endblock content %}

Enter fullscreen mode Exit fullscreen mode

signin.html

{% extends "base.html" %}{% load static %} {% block title %} Sign In {% endblock title %} 

{% block custom_head %}
<link rel="stylesheet" href="{% static 'css/signin.css' %}" />
{% endblock custom_head %} 

{% block content %}
<body class="text-center">
  <main class="form-signin">
    <form>
      <h1 class="h3 mb-3 fw-normal">Please sign in</h1>

      <div class="form-floating mt-2">
        <input
          type="text"
          class="form-control"
          id="floatingInput"
          name="username"
          placeholder="johndoe"
        />
        <label for="floatingInput">Username</label>
      </div>
      <div class="form-floating mt-2">
        <input
          type="password"
          class="form-control"
          id="floatingPassword"
          name="password"
          placeholder="Password"
        />
        <label for="floatingPassword">Password</label>
      </div>

      <button class="w-100 btn btn-lg btn-primary" type="submit">
        Sign in
      </button>
      <p class="mt-3">New user? <a href="signup.html">Sign up now</a></p>
    </form>
  </main>
</body>
{% endblock content %}

Enter fullscreen mode Exit fullscreen mode

signup.html

{% extends "base.html" %}{% load static %} {% block title %} Sign Up {% endblock title %} 

{% block custom_head %}
<link rel="stylesheet" href="{% static 'css/signin.css' %}" />
{% endblock custom_head %} 

{% block content %}
<body class="text-center">
  <main class="form-signin">
    <form>
      <h1 class="h3 mb-3 fw-normal">Please sign up</h1>

      <div class="form-floating mt-2">
        <input
          type="text"
          class="form-control"
          id="floatingInput"
          name="username"
          placeholder="johndoe"
        />
        <label for="floatingInput">Username</label>
      </div>
      <div class="form-floating mt-2">
        <input
          type="password"
          class="form-control"
          id="floatingPassword"
          name="password"
          placeholder="Password"
        />
        <label for="floatingPassword">Password</label>
      </div>

      <button class="w-100 btn btn-lg btn-primary" type="submit">
        Sign up
      </button>
      <p class="mt-3">
        Already Registered? <a href="signin.html">Sign in now</a>
      </p>
    </form>
  </main>
</body>
{% endblock content %}

Enter fullscreen mode Exit fullscreen mode

Running the server

Before we run the server, let's add a view function in the bag/views.py as this:

from django.shortcuts import render

# Create your views here.
def index(request):
    return render(request, "index.html")
Enter fullscreen mode Exit fullscreen mode

Also, add the view in the bag/urls.py:

from django.urls import path

from bag.views import index

urlpatterns = [
    path('', index, name='index'),
]

Enter fullscreen mode Exit fullscreen mode

Now we're ready to run the server using the command:

$ py manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
November 25, 2021 - 18:57:25
Django version 3.2.9, using settings 'GroceryBag.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Enter fullscreen mode Exit fullscreen mode

If you open the URL in your favorite browser, you will see this output:

This means we have everything working correctly. Similarly, you can replace index.html with other template files in the bag/views.py to test other web pages.

Conclusion

In this blog, we have learned about Template Inheritance and how to serve static files. We have fixed our templates now. In the next blog, we'll see how we can authenticate the user into our web app. Stay tuned!

Code till now: https://github.com/ashutoshkrris/Grocery-Bag/tree/blog2

Top comments (0)