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 5 → Other tutorials
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.
Source → 6ce33b05
Let's download the set from the Honke page.
↓ Click the Download button to skip
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.
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
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 liketemplates / polls /
orstatic / 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).
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'),
)
After setting, you can get css.
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>
before
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>
...
Yes. Just by adding a class to the table tag like this, it became a design like that easily.
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.
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
.
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.
Yes, it's a mess. This is because the css path is not correct.
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.
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.
The table is stuck to the header, but I think it's a good point.
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
topor
home`.
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.
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%}`.
TOP page
Selection page
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
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.
The black spots that were wasted have disappeared.
Try pressing the Vote
button without selecting anything.
With this kind of feeling, a "real" error check is automatically added.
If you send a value that is not in the options, it will look like this.
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.
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 aredebug
, ʻ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 -->
...
The message is now displayed like this. If you press the x button on the right side, this message disappears.
Recommended Posts