Tuesday, April 22, 2025

Django Gallery, News Template

You are strongly advised to check corresponding youtube video.


{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
    integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  </head>
  <body>

    {% block content%}

    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="{% url 'home' %}">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'about' %}">About</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'contact' %}">Contact</a>
      </li>
    </ul>
  </div>
</nav>

<div class="card-group">
  <div class="card">
    <img src="{% static 'images/img_1.jpg' %}" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
  <div class="card">
    <img src="{% static 'images/img_2.jpg' %}" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
  <div class="card">
    <img src="{% static 'images/img_3.jpg' %}" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
</div>

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
    integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
    integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
    integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
  </body>
</html>

Django Bootstrap 4

Let's grab B4 from CDN. CSS and veiwport will go to head section , JS files will go just before closing body tag, and we will use simplified B4 Navigation Bar.

Links for home, about and contact pages need to end up inside B4 navbar.


{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
    integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
  </head>
  <body>

    {% block content%}

    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="{% url 'home' %}">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'about' %}">About</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="{% url 'contact' %}">Contact</a>
      </li>
    </ul>
  </div>
</nav>

    {% block head_image %}
    <img src="{% static 'images/img_1.jpg' %}">
    {% endblock %}

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
    integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
    integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"
    integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
  </body>
</html>

Django Static Files

In Django, static files are the files such as CSS, JavaScript, images, and other supporting files that are used in web pages to enhance the user interface and experience. They are files that are served by Django as they are, without any modification, and are typically stored in a directory called static within the Django project.

To use these static files, you need to specify their URLs in your HTML templates or in your CSS and JavaScript files. Django provides a built-in tag called {% static %} that generates the URL for the static file and makes it available in your templates.

Ok, let's work with external CSS file. First, we will create static folder inside my_site directory.

And than CSS directory, inside static directory, where style.css will reside with our css code.

Copy/Paste css code from base.html to style.css:


body {
  margin: 0px;
}
ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background-color: #333;
}

li {
  float: left;
}

li a {
  display: block;
  color: white;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

li a:hover {
  background-color: #111;
}

p {
  background: lightyellow;
  width: 800px;
  border: 2px solid black;
  padding: 8px;
  margin: 2px;
  margin-bottom: 10px;
}

Of course, style.css must be linked in base.html

Also, have this line at the top of base template, to load css:


{% load static %}

This is our base.html now:


{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
  </head>
  <body>

    {% block content%}
    <ul>
      <li><a href="{% url 'home' %}">Home</a></li>
      <li><a href="{% url 'about' %}">About</a></li>
      <li><a href="{% url 'contact' %}">Contact</a></li>
    </ul>

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
  </body>
</html>

We are not done yet, static configuration must be in place in settings.py inside main my_projects directory, add these lines at the bottom of STATIC_URL section:


STATIC_URL = '/static/'

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

Check your pages, external CSS will work now.

Now we will add images to our simple cms. Create images directory in static directory (same level as css folder).

Find some .jpg images on your pc or grab it from internet. I will name them img_1.jpg, img_2.jpg, and img_3.jpg, for example.

We need to load it in base.html template, at least one for testing purposes:


{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
  </head>
  <body>

    {% block content%}
    <ul>
      <li><a href="{% url 'home' %}">Home</a></li>
      <li><a href="{% url 'about' %}">About</a></li>
      <li><a href="{% url 'contact' %}">Contact</a></li>
    </ul>

    <img src="{% static 'images/img_1.jpg' %}">

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
  </body>
</html>

Also, we can put image in dedicated block (section):


{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
  </head>
  <body>

    {% block content%}
    <ul>
      <li><a href="{% url 'home' %}">Home</a></li>
      <li><a href="{% url 'about' %}">About</a></li>
      <li><a href="{% url 'contact' %}">Contact</a></li>
    </ul>

    {% block head_image %}
    <img src="{% static 'images/img_1.jpg' %}">
    {% endblock %}

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
  </body>
</html>

For example, now we can use empty head_image block on custom pages to remove default image inherited from base template.

CSS Include in Django Base Template

Before CSS we will fix head section, namely title must be custom for every individual html page, which is also nice introduction to work with CSS code.


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
  </head>
  <body>

    {% block content%}
    <a href="{% url 'home' %}">Home</a> | <a href="{% url 'about' %}">About</a> | <a href="{% url 'contact' %}">Contact</a> |

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% endblock %}
  </body>
</html>

Now, let's create custom title section in, for example, home.html:


{% extends 'base.html' %}

{% block title %}
Custom Title On Home Page
{% endblock %}


{% block head %}
<h1>Custom H1 Heading from home.html</h1>
<p>Custom paragraph from home.html</p>
<p>Navigation is still provided by base template, base.html</p>
{% endblock %}

Ok, let's also have a little bit of text in custom pages, which means there must be paragraph section in base.html, too:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
  </head>
  <body>

    {% block content%}
    <a href="{% url 'home' %}">Home</a> | <a href="{% url 'about' %}">About</a> | <a href="{% url 'contact' %}">Contact</a> |

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
  </body>
</html>

Which means that we can use it in home.html for numerous custom paragraphs:


{% extends 'base.html' %}

{% block title %}
Custom Title On Home Page
{% endblock %}

{% block head %}
<h1>Custom H1 Heading from home.html</h1>
{% endblock %}

{% block para %}
<p>Custom Lorem Ipsum - First One....</p>
<p>Custom Lorem Ipsum - Second One....</p>
{% endblock %}

Nice, let's bring internal CSS in, and we will improve navigation in base.html too:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %} DEFAULT TITLE {% endblock %}</title>
    <style>
    body {
      margin: 0px;
    }
    ul {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #333;
    }

    li {
      float: left;
    }

    li a {
      display: block;
      color: white;
      text-align: center;
      padding: 14px 16px;
      text-decoration: none;
    }

    li a:hover {
      background-color: #111;
    }

    p {
      background: lightyellow;
      width: 800px;
      border: 2px solid black;
      padding: 8px;
      margin: 2px;
      margin-bottom: 10px;
    }

    </style>

  </head>
  <body>

    {% block content%}
    <ul>
      <li><a href="{% url 'home' %}">Home</a></li>
      <li><a href="{% url 'about' %}">About</a></li>
      <li><a href="{% url 'contact' %}">Contact</a></li>
    </ul>

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% block para %}
    <p>Lorem ipsum dolor sit amet, bla bla bla...</p>
    {% endblock %}

    {% endblock %}
  </body>
</html>

Django Base Template

Go to templates directory and create base.html, with this content:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Title</title>
  </head>
  <body>

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

  </body>
</html>

Basically, we are creating base template with navigation so that all other custom page (home, about, contact) can inherit from it.

Now, in every custom page, for example home.html, we need to import base.html:


{% extends 'base.html' %}

<h1>Heading in home.html</h1>

But if you check http://127.0.0.1:8000 for homepage, there's only content from base template there, and not custom stuff from home.html

Solution is to create sections (blocks) in base template, that can be substituted with custom content from each individual html page that inherits from base template:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Title</title>
  </head>
  <body>

    {% block content %}
    <a href="{% url 'home' %}">Home</a> | <a href="{% url 'about' %}">About</a> | <a href="{% url 'contact' %}">Contact</a> |

    {% block head %}
    <h1>DEFAULT H1 That Can Be Substituted in Custom Pages, if you need that.</h1>
    {% endblock %}

    {% endblock %}
  </body>
</html>

Now when we visit homepage (site "root", or home.html) we will have default situation, where H1 Heading will be visible. Or any other content from base.html, not just navigation.

But, important thing is that we can have custom content in all individual html pages - and that content will be actually visible:

Code in home.html, for example:


{% extends 'base.html' %}

{% block head %}

<h1>Custom H1 Heading from home.html</h1>

<p>Custom paragraph from home.html</p>

<p>Navigation is still provided by base template, base.html</p>

{% endblock %}

In Django, {% block %} is a template tag used to define a block of content in a parent template that can be overridden by a child template that extends the parent.

It is used in the parent template to define named sections of content that can be overridden in child templates. The block tag is followed by a unique name for the block, and the contents of the block are defined within the opening and closing tags.

Django Dynamic Navigation

This is our navigation file: 


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

The {% url %} template tag in Django is used to generate URLs for views.

This is useful because it allows you to easily create links to views without having to hard-code the URLs in your templates. If you need to change the URL for a view, you can simply update the URL pattern in the urls.py file, and all the links generated with {% url %} will automatically update to reflect the new URL.

After applied changes and server rerun we can access those links. This is what you will se in terminal where server is running: 


[26/Jul/2020 14:51:58] "GET / HTTP/1.1" 200 102
[26/Jul/2020 14:51:58] "GET / HTTP/1.1" 200 102
[26/Jul/2020 14:51:59] "GET /about/ HTTP/1.1" 200 104
[26/Jul/2020 14:51:59] "GET /about/ HTTP/1.1" 200 104
[26/Jul/2020 14:52:00] "GET /about/ HTTP/1.1" 200 104
[26/Jul/2020 14:52:00] "GET /about/ HTTP/1.1" 200 104
[26/Jul/2020 14:52:02] "GET /contact/ HTTP/1.1" 200 106
[26/Jul/2020 14:52:02] "GET /contact/ HTTP/1.1" 200 106
[26/Jul/2020 14:52:03] "GET /contact/ HTTP/1.1" 200 106
[26/Jul/2020 14:52:03] "GET /contact/ HTTP/1.1" 200 106
[26/Jul/2020 14:52:03] "GET /contact/ HTTP/1.1" 200 106
[26/Jul/2020 14:52:04] "GET / HTTP/1.1" 200 102
[26/Jul/2020 14:52:04] "GET / HTTP/1.1" 200 102

Django URL Routing, Navigation

We will create new html files to have something to work with: contact.html, about.html

Of course, they will be in templates directory.

Then we need to fix views.py


from django.shortcuts import render

def home(request):
    return render(request, 'home.html', {})

def about(request):
    return render(request, 'about.html', {})

def contact(request):
    return render(request, 'contact.html', {})

We need to fix local urls.py for new routes:


from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('about/', views.about, name = 'about'),
    path('contact/', views.contact, name = 'contact'),
]

Now, let's check those pages. We will visit links directly in address bar of browser, because there's no navigation in place - yet.

  • http://127.0.0.1:8000
  • http://127.0.0.1:8000/about
  • http://127.0.0.1:8000/contact

C:\my_projects>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
July 26, 2020 - 14:07:27
Django version 3.0.8, using settings 'my_projects.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
[26/Jul/2020 14:07:34] "GET / HTTP/1.1" 200 14
[26/Jul/2020 14:07:41] "GET /about/ HTTP/1.1" 200 15
[26/Jul/2020 14:07:48] "GET /contact/ HTTP/1.1" 200 17

Ok, let's add navigation to all pages. We will hardcode for now:


<a href="">Home</a> | <a href="about/">About</a> | <a href="contact/">Contact</a> |

Actually, that navigation will partially work - we will fix it in next tutorial on dynamic navigation.

Django First Html Page

First - create tamplate folder in my_site folder.

Then create home.html page in that template folder. We can just put simple H1 Heading there, or some lorem ipsum for test.

Then, go to views.py and create function that will respond to user request with home.html


from django.shortcuts import render

def home(request):
    return render(request, 'home.html', {})

We will create routing in local urls.py file (in my_site folder):


from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
]

We also need to change global routing file - urls.py, in main my_projects folder.


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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('my_site.urls'))
]

Then, run server and visit http://127.0.0.1:8000


C:\my_projects>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
July 26, 2020 - 11:15:27
Django version 3.0.8, using settings 'my_projects.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
[26/Jul/2020 11:15:29] "GET / HTTP/1.1" 200 25
[26/Jul/2020 11:15:30] "GET / HTTP/1.1" 200 25
[26/Jul/2020 11:15:31] "GET / HTTP/1.1" 200 25
[26/Jul/2020 11:15:31] "GET / HTTP/1.1" 200 25
[26/Jul/2020 11:15:31] "GET / HTTP/1.1" 200 25
[26/Jul/2020 11:15:31] "GET / HTTP/1.1" 200 25

You will be able to see whatever is in home.html

Django Dev Server


C:\my_projects>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
July 26, 2020 - 10:31:32
Django version 3.0.8, using settings 'my_projects.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

python manage.py runserver is a command in Django that starts the development server. When you run this command, Django will start a lightweight web server on your local machine, allowing you to view your Django project in a web browser.

The command python manage.py is used to interact with your Django project through the command line. runserver is a specific command that tells Django to start the development server.

Go to: http://127.0.0.1:8000/, you will see small rocket and message: The install worked successfully! Congratulations!

Go to: http://127.0.0.1:8000/admin/ to access Admin Panel, but you can't login because we didn't created admin credentials - yet.

Cancel server with Ctrl + Break, we need to create superuser - admin.

A superuser is a user account with all permissions to manage and modify the application. Superusers can access the admin site, which provides a graphical interface for managing the database and application settings.

We need to create a superuser during the initial setup of a Django application, so that we can have access to the admin site and perform administrative tasks such as creating and managing database objects, managing user accounts, etc. The superuser account also serves as a security measure, allowing only authorized users to perform such tasks.

But first - let's handle migrations:


C:\my_projects>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

C:\my_projects>

Superuser - admin creation with ultra secure admin password: "admin"


C:\my_projects>python manage.py createsuperuser
Username (leave blank to use 'user'): admin
Email address: admin@server.com
Password:
Password (again):
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

C:\my_projects>

C:\my_projects>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
July 26, 2020 - 10:50:29
Django version 3.0.8, using settings 'my_projects.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

Now we can visit 127.0.0.1:8000 and we can login with our ultra secure admin-pass combination: 127.0.0.1:8000/admin

Django Files, Project Structure


C:\my_projects>python manage.py startapp my_site

C:\my_projects>

Running the python manage.py startapp my_site command in the my_projects directory creates a new Django application named my_site.

This command creates a new directory called my_site, which contains several files and folders that make up the new Django application. These files include a models.py file for defining data models, a views.py file for handling HTTP requests and returning responses, a urls.py file for mapping URLs to views, and many other files and folders that are used to manage the application.

Once this command is executed, the my_site application is ready to be developed and integrated into the larger Django project. 


C:\my_projects>dir
 Volume in drive C is New Volume
 
 Directory of C:\my_projects

07/26/2020  10:18 AM    <DIR>          .
07/26/2020  10:18 AM    <DIR>          ..
07/26/2020  10:09 AM               652 manage.py
07/26/2020  10:18 AM    <DIR>          my_projects
07/26/2020  10:18 AM    <DIR>          my_site
               1 File(s)            652 bytes
               4 Dir(s)  77,952,106,496 bytes free

C:\my_projects>

This output indicates that the my_site app has been successfully created using the python manage.py startapp my_site command. 


C:\my_projects>cd my_site

C:\my_projects\my_site>dir
 Volume in drive C is New Volume

 Directory of C:\my_projects\my_site

07/26/2020  10:18 AM    <DIR>          .
07/26/2020  10:18 AM    <DIR>          ..
07/26/2020  10:18 AM                66 admin.py
07/26/2020  10:18 AM                93 apps.py
07/26/2020  10:18 AM    <DIR>          migrations
07/26/2020  10:18 AM                60 models.py
07/26/2020  10:18 AM                63 tests.py
07/26/2020  10:18 AM                66 views.py
07/26/2020  10:18 AM                 0 __init__.py
               6 File(s)            348 bytes
               3 Dir(s)  77,951,762,432 bytes free

C:\my_projects\my_site> 

Create file urls.py in this level (same level where we have views.py)

In Django, the urls.py file is used to map the URL patterns to their corresponding views. It acts as a routing mechanism for incoming requests to the web application.

When a user makes a request to a specific URL, Django checks the URL patterns defined in the urls.py file to find a matching view function. If a match is found, Django calls the corresponding view function to generate the HTTP response that will be sent back to the user.

Without the urls.py file, Django would not know how to route requests to the appropriate views, and the web application would not be able to function properly.

Django migrations are a way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema. Migrations are Django's way of managing and applying changes to the database schema over time, as you evolve your application.

When you make changes to your models, you can create a migration that specifies the changes, and then apply that migration to your database to make the changes to the schema. This helps you keep your database schema in sync with your models and makes it easier to manage changes to your application over time.

Go to C:\my_projects\my_projects and find settings.py. Open it and add 'my_site' at the bottom of INSTALLED APPS:


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'my_site',
]

Installed apps in Django are the components or modules that are included in the project to provide additional functionality. These apps can be either built-in apps provided by Django itself or third-party apps developed by other developers.

By default, when a new Django project is created, several built-in apps are automatically included in the project's settings.py file, such as:

  • django.contrib.admin: provides a powerful web-based admin interface for managing the project's data.
  • django.contrib.auth: provides user authentication functionality.
  • django.contrib.contenttypes: provides generic relations between models.
  • django.contrib.sessions: provides session management functionality.
  • django.contrib.messages: provides message passing functionality.
  • django.contrib.staticfiles: provides a simple way to manage static files such as images, CSS, and JavaScript.

However, developers can install additional third-party apps from the Python Package Index (PyPI) or develop their own custom apps for their specific needs. These apps can be added to the INSTALLED_APPS list in the project's settings.py file to include them in the project.

Django Creating Project


C:\>django-admin startproject my_projects

C:\>

The command django-admin startproject my_projects creates a new Django project named my_projects. It creates a new directory with the same name as the project and populates it with the necessary files and directories to start a new Django project.

The directory structure will include a manage.py file, a project-specific settings.py file, and other files and directories required for the project to run. This command is run in the command prompt on a Windows machine, specifically in the root directory (C:) in this case. 


C:\>cd my_projects

C:\my_projects>dir
 Volume in drive C is New Volume

 Directory of C:\my_projects

07/26/2020  10:09 AM    <DIR>          .
07/26/2020  10:09 AM    <DIR>          ..
07/26/2020  10:09 AM               652 manage.py
07/26/2020  10:09 AM    <DIR>          my_projects
               1 File(s)            652 bytes
               3 Dir(s)  78,327,861,248 bytes free

C:\my_projects> 

cd my_projects: This command changes the current working directory to the "my_projects" directory created in the previous step.

dir: This command lists the contents of the current directory, showing that it contains a subdirectory called "my_projects" and a file called "manage.py". The "my_projects" subdirectory is where the main Django project files are located, while "manage.py" is a script used to manage the project (e.g. running the development server, running tests, etc.). 


C:\my_projects\my_projects>dir
 Volume in drive C is New Volume

 Directory of C:\my_projects\my_projects

07/26/2020  10:09 AM    <DIR>          .
07/26/2020  10:09 AM    <DIR>          ..
07/26/2020  10:09 AM               415 asgi.py
07/26/2020  10:09 AM             3,223 settings.py
07/26/2020  10:09 AM               774 urls.py
07/26/2020  10:09 AM               415 wsgi.py
07/26/2020  10:09 AM                 0 __init__.py
               5 File(s)          4,827 bytes
               2 Dir(s)  77,955,743,744 bytes free

C:\my_projects\my_projects> 

Django Installation


Microsoft Windows [Version 10.0.18363.959]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\user>pip install django
Collecting django
  Downloading Django-3.0.8-py3-none-any.whl (7.5 MB)
|████████████████████████████████| 7.5 MB 3.2 MB/s
Collecting pytz
  Using cached pytz-2020.1-py2.py3-none-any.whl (510 kB)
Collecting asgiref~=3.2
  Using cached asgiref-3.2.10-py3-none-any.whl (19 kB)
Collecting sqlparse>=0.2.2
  Using cached sqlparse-0.3.1-py2.py3-none-any.whl (40 kB)
Installing collected packages: pytz, asgiref, sqlparse, django
Successfully installed asgiref-3.2.10 django-3.0.8 pytz-2020.1 sqlparse-0.3.1

C:\Users\user>

This command installs the latest version of the Django web framework, along with its dependencies, such as pytz and sqlparse. The output shows the progress of the installation, including the downloading and installation of the packages. Finally, the output indicates that the installation was successful.

Tkinter - Text Widget

In this tutorial we will talk about Tkinter Text Widget. Make sure that you can run this source, and than we will explain.

Please note, we are reading a textual file LICENCE.txt, which is located in Python install folder - this script must be in a folder where that txt file resides, too. You can set a path to some other txt file.

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

file = open("LICENSE.txt", "r")

t = Text(top_win, padx = 20, pady = 20, width = 50, height = 20,
         cursor = "dot", relief = RIDGE, bd = 10, bg = "lightyellow",
         fg = "red", selectbackground = "yellow", selectforeground = "black",
         font = "Verdana")

for x in file.read():
    t.insert(END, x)

file.close()
t.pack(side = TOP, anchor = NW)
top_win.mainloop()

This is line that will open LICENCE.txt for reading:

file = open("LICENSE.txt", "r")

And this is source for Text Widget. We have padding set, width and height set, type of cursor, type of relief, border width, background color, text color, font type is Verdana, and background and foreground color set when we select part of text:

t = Text(top_win, padx = 20, pady = 20, width = 50, height = 20,
         cursor = "dot", relief = RIDGE, bd = 10, bg = "lightyellow",
         fg = "red", selectbackground = "yellow", selectforeground = "black",
         font = "Verdana")

With for loop we are reading txt file content. Otherwise you will not see any text on screen, just borders and colors:

for x in file.read():
    t.insert(END, x)

This line will close file:

file.close()

As with other widgets we must pack our text section, and at the end of script is standard mainloop:

t.pack(side = TOP, anchor = NW)
top_win.mainloop()

Consider watching corresponding YouTube tutorial on Tkinter Text Widget.

This is end of this tutorial and YT playlist on Tkinter, and you have a lot of other Python tutorials on this site and WebDevPro channel.

Learn More:

Free Python Programming Course
Python Examples
Python How To
Python Modules 

YouTube WebDevPro Tutorials

Tkinter - Scrollbars

As with menu Tkinter widgets, we will need some explanations with Labels what specific widgets are used for:

lab_1 = Label(top_win, text ="Scrolls are Weird")
lab_1.pack(side = TOP, anchor = NW)

Scrollbars must be positioned inside some Tk window: 

scr_bar = Scrollbar(top_win)
scr_bar.pack(side = RIGHT, fill = Y)

Important - now we need Listbox with yscrollcommand that will target Scrollbar, in this case scr_bar:

items = Listbox(top_win, yscrollcommand = scr_bar.set)

If we are lazy to invent items, there is a for loop to populate a list:

for x in range(100):
    items.insert(END, "Item: " + str(x))

Now it's time to pack Listbox with items:

items.pack(side = LEFT, fill = BOTH)

Interesting thing with Scrollbars, they must be configured to target items, using this line:

scr_bar.config(command = items.yview)

This is full working source:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("200x200")

lab_1 = Label(top_win, text ="Scrolls are Weird")
lab_1.pack(side = TOP, anchor = NW)

scr_bar = Scrollbar(top_win)
scr_bar.pack(side = RIGHT, fill = Y)

items = Listbox(top_win, yscrollcommand = scr_bar.set)

for x in range(100):
    items.insert(END, "Item: " + str(x))

items.pack(side = LEFT, fill = BOTH)

scr_bar.config(command = items.yview)
top_win.mainloop()

Scrollbars are little bit weird, so definitely check YouTube tutorial on Scrollbars.

Tkinter - Scale

This source will produce simple Tkinter GUI with horizontal scale on it, in value range from 1 to 100, using label "Range". 

Scale will be packed to center of the top_win. At the bottom of the scale we will have submit Button. 

No functions at the moment, just GUI:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

scale = Scale(top_win, label = "Range", from_ = 1, to = 100,
              orient = HORIZONTAL)
scale.pack(anchor = CENTER)

btn_1 = Button(top_win, text = "Submit")
btn_1.pack(anchor = CENTER)

top_win.mainloop()

So, a source to create scale is this one:

scale = Scale(top_win, label = "Range", from_ = 1, to = 100,
              orient = HORIZONTAL)
scale.pack(anchor = CENTER)

What about a source with function that will print something on Python Shell based on values from Scale:

from tkinter import *
import tkinter.messagebox as mb
import os

top_win = Tk()
top_win.geometry("800x800")

def select():
    selected = real_val.get()
    print("Selected From Range: ", selected)

    if selected >= 50:
        print("More Than 50")

real_val = IntVar()

scale = Scale(top_win, label = "Range", length = 200, from_ = 1, to = 100,
              orient = HORIZONTAL, troughcolor = "red", variable = real_val)
scale.pack(anchor = CENTER)

btn_1 = Button(top_win, text = "Submit", command = select)
btn_1.pack(anchor = CENTER)

top_win.mainloop()

Function select() will get and check a point from scale. That value will be printed in Python Shell.

Also, if value is higher than 50, that will be printed too.

def select():
    selected = real_val.get()
    print("Selected From Range: ", selected)

    if selected >= 50:
        print("More Than 50")

Value is stored in real_val using this line:

real_val = IntVar()

To connect scale with real_val, use these lines:

scale = Scale(top_win, label = "Range", length = 200, from_ = 1, to = 100,
              orient = HORIZONTAL, troughcolor = "red", variable = real_val)
scale.pack(anchor = CENTER)

At the end we need to connect a button with function, using "command = ":

btn_1 = Button(top_win, text = "Submit", command = select)
btn_1.pack(anchor = CENTER)

There is corresponding YouTube tutorial on Tkinter Scale.

Tkinter Introduction - Top Widget, Method, Button

First, let's make shure that our tkinter module is working ok with simple  for loop that will spawn 5 instances of blank Tk window .  ...