Python Django Tutorial (6)

It is a material for study sessions This time, I will explain about bootstrap completely away from the original tutorial.

Tutorial Tutorial Tutorial 1 Tutorial 2 Tutorial 3 Tutorial 4 Tutorial 5Other tutorials

Source (github)

Use Bootstrap

Designing html is difficult, isn't it? It would be nice if the designer could prepare a nice html, but unfortunately I can't hope for such a thing in the tutorial. However, it is difficult for an amateur to make a beautiful css from scratch. Bootstrap for you! bootstrap is a framework that provides responsive design css, javascript, font, icon, etc. that can be used for free (commercial use is also possible!).

Responsive design is a design that automatically adjusts the display width and layout according to the size of the browser. The same html can be reused on PCs, smartphones, and tablets.

Honke Introduction to Tohoho's Bootstrap What is Bootstrap? (wikipedia)

django also has a library for linking with bootstrap, which is just right for practicing the placement of css and javascript. I would like to deal with it in the tutorial.

Bootstrap download and deployment

Source → 6ce33b05

Let's download the set from the Honke page.

Kobito.2hc2qO.png

↓ Click the Download button to skip

Kobito.7n9C3e.png

This time, we will use ** Bootstrap ** on the far left. You can download a zip file called bootstrap-3.3.6-dist.zip. Let's unzip this.

Kobito.9C8A5v.png 3.3.6 has this file structure.

Next, create a folder called static in the same hierarchy as manage.py in the tutorial, and throw in all the contents of the unzipped bootstrap there. The file structure after the move should be as follows.

(tutorial)$ tree .
├── db.sqlite3
├── manage.py
├── polls
│   ├── __init__.py
│   ├── ...
│   └── views.py
├── requirements.txt
├── static  #Directory added this time
│   ├── css
│   │   ├── bootstrap-theme.css
│   │   ├── bootstrap-theme.css.map
│   │   ├── bootstrap-theme.min.css
│   │   ├── bootstrap-theme.min.css.map
│   │   ├── bootstrap.css
│   │   ├── bootstrap.css.map
│   │   ├── bootstrap.min.css
│   │   └── bootstrap.min.css.map
│   ├── fonts
│   │   ├── glyphicons-halflings-regular.eot
│   │   ├── glyphicons-halflings-regular.svg
│   │   ├── glyphicons-halflings-regular.ttf
│   │   ├── glyphicons-halflings-regular.woff
│   │   └── glyphicons-halflings-regular.woff2
│   └── js
│       ├── bootstrap.js
│       ├── bootstrap.min.js
│       └── npm.js
└── tutorial
    ├── __init__.py
    ├── ...
    └── settings.py

Change django settings

Source → 73d94740a Official documentation (English) Official document (Japanese, but django 1.4)

The displayed contents of pages such as http: // localhost: 8000 / polls / created in the tutorial vary depending on the contents of the DB. Such pages (URLs) are called dynamic pages, dynamic pages, dynamic content, and so on. On the other hand, css and js files such as bootstrap.css always return the same contents when accessing the same URL. Such pages are called static pages, static content, static files, and so on. Since the content of dynamic content changes with each access, execute the program (python, ruby, php, etc.) and You need to change the page content. On the other hand, static content does not change, so there is no need to make inquiries for each access. The contents are cached in the browser. Caching speeds up reading and reduces the load on the server, but it also has the disadvantage that changes in the contents are not reflected.

In django, static files such as image files, css files, and javascript files are managed as static files. It is easy to manage by putting it in one place during operation.

The way to put them together is $ ./manage.py collectstatic, but you don't need to use this command while running on runserver. I will explain deploy (server installation) soon, so I will explain in detail at that time.

Static files are raked up in the static directory under each app, without adding the URL to urls.py You can access it at http: // localhost: 8000 / static /. This tutorial will not cover it, but if you need polls-specific css Install it as polls / static / polls / css / polls.css Access as http: // localhost: 8000 / static / polls / css / polls.css. By the way, static files like the django admin site are under django / contrib / admin / static / admin /.

When it is a template, it looks like polls / templates / polls /. It may seem verbose to give the app a name like templates / polls / or static / polls /, It seems that it has such a structure because of avoidance of name collision and code merit.

However, the static directory that is searched by default is under the app (INSTALLED_APPS in settings.py) Only static files. This time, we created the static directory in the same hierarchy as manage.py, so we need to add settings so that this directory can also be read. To add a directory where static files are located, specify the directory you want to add to STATICFILES_DIRS with a tuple (or list).

Kobito.1pM05v.png Before setting, it becomes 404. (For various reasons, it is started on port 13000)

tutorial/settings.py


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

Kobito.6wqhns.png After setting, you can get css.

Template modification

Source → 63cdd0cc

To read a static file from within the template, use the template tag {% static%}. For example, when loading bootstrap.css <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" /> Write as follows. To use the {% static%} tag, you must first write {% load staticfiles%}.

First, let's load bootstrap.css on the list page.

polls/templates/polls/index.html


{% load staticfiles %}  <!--← Add-->
<html>
  <head> <!--← Add-->
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" /> <!--← Add-->
  </head> <!--← Add-->
<body>
  <table border="1">
    <tr>
      <th>Contents of question</th>
      <th>release date</th>
      <th></th>
    </tr>
    {% for question in questions %}
    <tr>
      <td>{{ question.question_text }}</td>
      <td>{{ question.pub_date }}</td>
      <td><a href="{% url 'polls:detail' question.pk %}">To detail screen</a></td>
    </tr>
    {% endfor %}
  </table>
</body>
</html>

Kobito.mXJ2pb.png before

Kobito.aIXL4h.png after

I don't feel the benefits of css just because it's getting smaller. css shows its true value by specifying class in the html tag.

Let's try css for the table for the time being. According to bootstrap page, if you add a table class, you can design for table. I will also try striped.

polls/templates/polls/index.html


...
<body>
  <table border="1" class="table table-striped">
    <tr>
      <th>Contents of question</th>
...

Kobito.RIiscq.png

Yes. Just by adding a class to the table tag like this, it became a design like that easily.

Template extension

Official Documents Official documentation (Japanese, but django 1.4)

This template is already in use, but it will only show its true value if it is inherited. qiita, bootstrap docs, django docs, anywhere, but any site The headers and footers when moving pages are basically the same, only the contents of the page have changed, right? Naturally, considering the unity within the site, the framework is the same within the same site, and only a part changes. Create a base template and inherit from that template, just as you would with a class generic view By overriding only the part you want to change, you can reduce the amount of code and create a site that is resistant to changes.

In this section, we will create a base template and replace the template created in the tutorial. Get ready to easily apply the bootstrap design.

Creating a base template

Source → 741a853886

Anyway, let's prepare a base template. As was the case with the static file, in the case of template, prepare the templates directory in the same hierarchy as manage.py. Use it as a base template storage.

If there is an app that can be used as a base, such as dashboard, I think it may be possible to put it there.

In the case of template, as with static, by default it only looks at the templates directory under the app. Let's change settings.py as we did for static. In the case of template, describe the directory you want to add to DIRS in TEMPLATES.

tutorial/settings.py


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  #←← Add the contents here
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Next, let's create base.html in templates. The main content is, I will use bootstrap starter-template. It is necessary to modify the contents, but for the time being, let's paste the same thing and save it as base.html.

Preparation for inheritance and modification of base

Source → 2cca1ce20eb

I want to fix it while looking at it for the time being, so Let's modify polls / templates / polls / index.html to inherit base.html. It's easy to do, just write {% extends" base.html "%} in the head.

polls/templates/polls/index.html


{% extends "base.html" %}
{% load staticfiles %}
<html>
...

If you look at http: // localhost: 8000 / polls / in this state, it should look like the following.

Kobito.VImUOU.png

Yes, it's a mess. This is because the css path is not correct.

Kobito.PWaw7X.png

For the time being, here is the corrected path of css and js. Modifying html has nothing to do with django, so I'll skip it. Please check the source.

Add and overwrite change blocks

Source → 8a3fe39358

Finally the main line. Let's display the question list in the "Bootstrap starter template" part that is currently displayed on the screen. The contents of <div class =" container "> in html correspond to this part, so delete it and delete it. Allows overwriting at the inheritance destination.

templates/base.html(Before correction)


    <div class="container">

      <div class="starter-template">
        <h1>Bootstrap starter template</h1>
        <p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
      </div>

    </div><!-- /.container -->

templates/base.html(Revised)


    <div class="container">
    {% block contents %}{% endblock %}
    </div><!-- /.container -->

Erase the contents and prepare the {% block%} tag. The name can be anything, but here it is contents.

Next, modify the template of the inheritance destination.

polls/templates/polls/index.html(Before correction)


{% extends "base.html" %}
{% load staticfiles %}
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}" />
  </head>
<body>
  <table border="1" class="table table-striped">
    <tr>
      <th>Contents of question</th>
      <th>release date</th>
      <th></th>
    </tr>
    {% for question in questions %}
    <tr>
      <td>{{ question.question_text }}</td>
      <td>{{ question.pub_date }}</td>
      <td><a href="{% url 'polls:detail' question.pk %}">To detail screen</a></td>
    </tr>
    {% endfor %}
  </table>
</body>
</html>

polls/templates/polls/index.html(Revised)


{% extends "base.html" %}

{% block contents %}
  <table border="1" class="table table-striped">
    <tr>
      <th>Contents of question</th>
      <th>release date</th>
      <th></th>
    </tr>
    {% for question in questions %}
    <tr>
      <td>{{ question.question_text }}</td>
      <td>{{ question.pub_date }}</td>
      <td><a href="{% url 'polls:detail' question.pk %}">To detail screen</a></td>
    </tr>
    {% endfor %}
  </table>
{% endblock contents %}

The html tag, head tag, and body tag are not required because they are set in the inheritance source (templates / base.html). I want to place the contents of the <table> tag inside the contents, so It starts with {% block contents%} and ends with {% endblock contents%}. No argument is required for {% endblock%}, but as the contents of the block grow larger, it becomes impossible to know which block was closed. If {% block%} and {% endblock%} are separated, it is better to write as much as possible.

By the way, if the name is not paired with {% block contents%} like {% endblock content%}, an error will occur.

Now, let's check what happened with the browser.

Kobito.OTzMq7.png

The table is stuck to the header, but I think it's a good point.

Modify base.html and add polls / base.html

Source → ʻe722778ee`

Now that the TOP page has been created, you can access it at http: // localhost: 8000 / Edit tutorial / urls.py. However, since there is no actual view for the TOP page, the content is the same as polls / for the time being. The name is ʻindex, but please give it any name you like, such as toporhome`.

tutorial/urls.py


from django.conf.urls import include, url
from django.contrib import admin

from polls.views import index  #← Add

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^polls/', include('polls.urls', namespace='polls')),
    url(r'^$', index, name='index'),  #← Add
]

Then, modify the wording and links of base.html.

templates/base.html


    <nav class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
		...
          <a class="navbar-brand" href="{% url 'index' %}">Tutorial</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="{% url 'polls:index' %}">polls</a></li>
            <li class=""><a href="{% url 'admin:index' %}">admin</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>

Here is a little ingenuity. The <li> of polls in the <div id =" navbar "> has a class =" active ". With ʻactive`, the header is highlighted as shown below, making it easier to see where you are on the page. Kobito.fUGtFd.png

I always want to add active in the template in polls, but I don't want to highlight it in other apps. Therefore, change this part to {% block%} so that it can be rewritten.

templates/base.html


<li class="{% block nav_polls %}{% endblock %}"><a href="{% url 'polls:index' %}">polls</a></li>

However, if nothing is done, all the templates in polls / templates / polls will have to be changed. Therefore, create polls / templats / polls / base.html, and use the template under polls / templats / polls. It inherits polls / base.html.

base.html
   └ polls/base.html
       ├ polls/index.html
       ├ polls/detail.html
       └ polls/results.html

polls/templates/polls/base.html


{% extends "base.html" %}

{% block nav_polls %}active{% endblock %}

Add active to nav_polls

polls/templtes/polls/index.html


{% extends "polls/base.html" %}

Inherit polls / base.html instead of base.html

By the way, let's change it so that detail.html and results.html are also inherited. To fix it, add {% extends" polls / base.html "%} to the first line, as in ʻindex.html. Just enclose the contents in {% block contents%}`.

Kobito.pxgSZ5.png

TOP page

Kobito.YlkGRA.png

Selection page

Kobito.VjLnSb.png

Result page

Django Bootstrap

Up to this point, I used django's template function to allocate bootstrap css by myself. I don't think I felt much benefit. This chapter introduces django-bootstrap, which allows you to easily replace the django design.

https://github.com/dyve/django-bootstrap3 http://django-bootstrap3.readthedocs.org/en/latest/index.html

Introduction and replacement of Form

Source → 498065d9fff

To checkouts the source and try it, run pip install -r requirements.txt.

You can easily enter with pip.

Due to the version of bootstrap, the name will be django-bootstrap3. Be careful not to forget to add "3".

(tutorial)$ pip install django-bootstrap3
Collecting django-bootstrap3
  Downloading django-bootstrap3-6.2.2.tar.gz
Building wheels for collected packages: django-bootstrap3
  Running setup.py bdist_wheel for django-bootstrap3 ... done
...  
  
Successfully built django-bootstrap3
Installing collected packages: django-bootstrap3
Successfully installed django-bootstrap3-6.2.2

Then open tutorial / settings.py and add bootstrap3 to INSTALLED_APPS.

tutorial/settings.py


INSTALLED_APPS = (
    'django.contrib.admin',
...
    'django.contrib.staticfiles',
    'bootstrap3',  #← Add
    'polls',
)

This is the end of the installation work. Let's rewrite the Form at once. This time, I will rewrite the form output by polls / templates / polls / detail.html.

Instead of outputting the form with {{form}}, use the {% bootstrap_form%} template tag to output the form. You need to load bootstrap3 before using it.

polls/templates/polls/detail.html


{% extends "polls/base.html" %}
{% load bootstrap3 %}  <!--← Add-->

{% block contents %}
<h1>{{ question.question_text }}</h1>

<form action="" method="post">
  {% csrf_token %}
  {% bootstrap_form form %} <!--← Correction-->
  <input type="submit" value="Vote" />
</form>
{% endblock contents %}

One line is added and one line is modified. Let's check what happened on the screen.

Kobito.EUxhO5.png

The black spots that were wasted have disappeared. Try pressing the Vote button without selecting anything.

Kobito.d0ide3.png

With this kind of feeling, a "real" error check is automatically added.

Kobito.0QI9Rr.png

If you send a value that is not in the options, it will look like this.

builtin settings

Source → 1f19af40

By the way, the Form has become so beautiful that it can be mistaken for just two lines. However, it is troublesome to write {% load bootstrap3%} one by one. Write in settings.py to automatically load the template tag for bootstrap3.

tutorial/settings.py


TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            'builtins': [
                'bootstrap3.templatetags.bootstrap3',  #←←← Add this
            ],
        },
    },
]

By the way, you can write here from django 1.9. Prior to django1.8, you can do the same by using the django.template.base.add_to_builtins method. When using the {% load%} tag, it was only bootstrap3, but when specifying it with builtins, bootstrap3.templatetags.bootstrap3 Please note that you can only go if you include the PATH up to template tags like.

Delete the description of load from polls / templates / polls / detail.html and make sure that no error occurs.

message display

Source → ʻa2d08a455`

Now, if you select an option and vote, it will just jump to the result page. Let's output what the user voted for on the result page.

django documentation django documentation (Japanese)

django provides a mechanism for carrying some information to the next page as messages. To use it, INSTALLED_APPS in settings.py must contain django.contrib.messages.

As with admin etc., it is included by default, so there is no need to modify the settings.

First, let's add a message. This time, when I voted, I want to show which selection I made, so edit form_valid in polls / views.py. To add a message, just pass the message you want to display as request to the messages.success function.

In addition to success, there are debug, ʻinfo, warning, and ʻerror.

polls/views.py


from django.contrib import messages
...

class Detail(SingleObjectMixin, FormView):
...
    def form_valid(self, form):
        form.vote()
        choice = form.cleaned_data['choice']
        messages.success(self.request, '"%s"Voted for' % choice)
        return super().form_valid(form)

It will be a little smoother if you return a message (or an instance of choice) with the return value of vote.

Next is the display. I want to display the message on all pages, so add it to base.html. django-bootstrap3 also supports displaying messages, so it's easy to do this too.

templates/base.html


...
    <div class="container">
    {% if messages %}
    {% bootstrap_messages messages %}
    {% endif %}
    {% block contents %}{% endblock %}
    </div><!-- /.container -->
...

Kobito.joC23A.png

The message is now displayed like this. If you press the x button on the right side, this message disappears.


In the next tutorial, we will explain the test (equivalent to the original tutorial 5). [To the next tutorial](http://qiita.com/maisuto/items/cce169a2455b116e2f82)

Other tutorials

Recommended Posts

Python Django Tutorial (5)
Python Django Tutorial (2)
Python Django Tutorial (6)
Python Django Tutorial (7)
Python Django Tutorial (1)
Python Django tutorial tutorial
Python Django Tutorial (3)
Python Django Tutorial (4)
Python Django tutorial summary
Python tutorial
Python Django Tutorial Cheat Sheet
Python tutorial summary
django tutorial memo
Start Django Tutorial 1
Django 1.11 started with Python3.6
[Docker] Tutorial (Python + php)
Django python web framework
Django Polymorphic Associations Tutorial
django oscar simple tutorial
Try Debian + Python 3.4 + django1.7 ...
[Personal notes] Python, Django
Python OpenCV tutorial memo
[Python tutorial] Data structure
Django Girls Tutorial Note
Cloud Run tutorial (python)
Python Django CSS reflected
Do Django with CodeStar (Python3.6.8, Django2.2.9)
Get started with Django! ~ Tutorial ⑤ ~
Introduction to Python Django (2) Win
[Python tutorial] Control structure tool
Python
Do Django with CodeStar (Python3.8, Django2.1.15)
Python3 + Django ~ Mac ~ with Apache
Create ToDo List [Python Django]
Getting Started with Python Django (1)
Django
Getting Started with Python Django (4)
Getting Started with Python Django (3)
Get started with Django! ~ Tutorial ⑥ ~
Install Python 3.7 and Django 3.0 (CentOS)
[Python] Decision Tree Personal Tutorial
GAE + python + Django addictive story
Getting Started with Python Django (6)
Getting Started with Python Django (5)
Until Python [Django] de Web service is released [Tutorial, Part 1]
8 Frequently Used Commands in Python Django
Create new application use python, django
python + django + scikit-learn + mecab (1) on heroku
python + django + scikit-learn + mecab (2) on heroku
Run python3 Django1.9 with mod_wsgi (deploy)
Django Girls Tutorial Summary First Half
Stumble when doing the django 1.7 tutorial
Deploy the Django tutorial to IIS ①
Install Python framework django using pip
Introduction to Python Django (2) Mac Edition
[Python Tutorial] An Easy Introduction to Python
Learning history for participating in team app development in Python ~ Django Tutorial 5 ~
Learning history for participating in team app development in Python ~ Django Tutorial 4 ~
Learning history for participating in team app development in Python ~ Django Tutorial 1, 2, 3 ~
Learning history for participating in team app development in Python ~ Django Tutorial 6 ~
Learning history for participating in team app development in Python ~ Django Tutorial 7 ~