Recently, I think that many people choose Python for reasons such as "strong in machine learning" and "easy".
That's the wall of Django that people run into when they want to write the Web. (That's not the case? No, it's difficult!)
At first, I did only the Django Tutorial in Japanese, and after that I read all the English literature and studied by looking at the company code, but it was quite difficult.
I want to write the web, but ◯ uby is easier to write than Python, so ◯ uby is better ... So that I don't end up with Django, I've packed the basics and applications of Django that I've studied so far. I will write articles that can be mastered at the fastest speed! (It will be 3 or 4 articles long)
If you don't have Django,
$ pip install django
It seems that you can install it with.
I downloaded Python from a distribution called Anaconda, so it was included from the beginning. It's okay to eat up the capacity of your computer! I recommend you to download it from Anaconda. Besides Django, it's convenient because it's included from the beginning!
* Click here to install Anaconda * Easy-to-understand article about Anaconda installation
For those who can already write the Web when studying the Web
I almost always hear that
You are told! !! !!
It's certainly a good study to make everything by yourself, but I think it's difficult (or almost impossible?) To make everything from nothing.
So, in this article, I'm going to proceed with the feeling of "** Learn Django while making one app in order **".
We will also create a repository on GitHub, so please refer to that for the code as well. (If there are people who say "It was helpful!" Throughout not only this article but also future articles, please add a star!)
* Click here for GitHub repository
Since I want to implement various functions, the content of the app emphasizes practicality rather than fun.
As for the content, I would like to create a "management tool".
We are assuming two types of users, manager and worker. The manager creates a work set for the worker to take charge of, checks the working status of the worker, and checks the worker's work when it is completed. Workers, on the other hand, read help pages about their jobs and check their working conditions.
If you come up with other interesting functions, I will implement them, but for the time being, I would like to implement them in this area.
First, create a project. In Django, one application is called a project, and several applications are running under one project.
Move to the directory where you want to create the application and execute the following command.
(Manager_project
is the name I gave to this application, so anything is fine in reality.)
$ django-admin startproject manager_project
The project has been created.
-- manager_project/
-- manager_project/
-- __init__.py
-- setting.py
-- urls.py
-- wsgi.py
-- manage.py
I think that the file structure is.
Of these, the ones we mainly use are setting.py
, ʻurls.py, and
manage.py. (However, this is only used for one point, and the main development will be
models.py and
views.py` to be created from now on)
Next, let's make an app.
$ cd path/to/manager_project
(If you continue to hit from the previous command,$ cd manager_Just project is fine. This directory"master directory"I will call it)
#For confirmation
$ ls
manage.py manager_project
#Is it?(One level higher manager_Please enter into the project)
$ python manage.py startapp manager
You should now have an app called manager
.
The file structure in manager is as follows.
-- manager
-- migrations
-- __init__.py
-- admin.py
-- apps.py
-- models.py
-- tests.py
-- views.py
Of these, the ones I often use are models.py
, views.py
, and tests.py
.
I usually play around here.
Now you have to report to the project that you've created an app!
Here, change setting.py
as follows.
setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'manager', #Additional part
]
The app is now complete.
Before we actually write the code, let's take a look at how Django responds after receiving a request.
It's simple, isn't it? That's it!
First the client sends an http request (like https://google.com!)
In urls.py, there are some url regular expressions and corresponding views, and if there is a matching url, go to that View, otherwise it will return something like "page not found" (403) Or 404).
As an aside, I would like to introduce a site that is extremely useful when writing regular expressions! Online Regrex Tester
View is written in views.py
and is the one that does the main operation. The necessary data from the database is fetched from the template as the original html file, the two are mixed, and returned as an HTTP response.
This allows the client to see a page with the data they want in a clean format!
So let's actually write the code.
There are things that I want to implement first, such as the login function and Hijack function, but it will be a little complicated, so this time I will implement a screen that displays a list of workers.
Create a model and create data. (Because it is the beginning, I will put all the code. Since it will be long, I will put only a part from the next time.)
models.py
from django.db import models
class Person(models.Model):
MAN = 0
WOMAN = 1
HOKKAIDO = 0
TOHOKU = 5
TOKYO = 10
CHIBA = 11
KANAGAWA = 12
SAITAMA = 13
TOCHIGI = 14
IBARAGI = 15
CHUBU = 20
KANSAI = 25
CHUGOKU = 30
SHIKOKU = 35
KYUSHU = 40
OKINAWA = 45
#name
name = models.CharField(max_length=128)
#birthday
birthday = models.DateTimeField()
#sex
sex = models.IntegerField(editable=False)
#Birthplace
address_from = models.IntegerField()
#Current address
current_address = models.IntegerField()
#mail address
email = models.EmailField()
class Manager(models.Model):
#Department constant
DEP_ACCOUNTING = 0 #accounting
DEP_SALES = 5 #Sales
DEP_PRODUCTION = 10 #Manufacturing
DEP_DEVELOPMENT = 15 #development of
DEP_HR = 20 #human resources
DEP_FIN = 25 #Finance
DEP_AFFAIRS = 30 #General affairs
DEP_PLANNING = 35 #Planning
DEP_BUSINESS = 40 #business
DEP_DISTR = 45 #distribution
DEP_IS = 50 #Information system
#Man
person = models.ForeignKey('Person')
#Department
department = models.IntegerField()
#When to arrive
joined_at = models.DateTimeField()
#When I quit
quited_at = models.DateTimeField(null=True, blank=True)
class Worker(models.Model):
#Man
person = models.ForeignKey('Person')
#When to arrive
joined_at = models.DateTimeField()
#When I quit
quited_at = models.DateTimeField(null=True, blank=True)
#Boss in charge
manager = models.ForeignKey('Manager')
Here is the code description.
Model classes are basically created by inheriting models.Model
.
The attribute must specify its data type, for example ʻIntegerField` for integer values.
--CharField: Character string (max_length must be specified for memory management) --IntegerField: Integer --DateTimeField: Time
There is also an attribute to put raw data such as
There are also attributes that represent the relationships between models, such as. Model field reference (list of fields)
For example, ForeignKey is a field that indicates a "1: many" relationship. In the Manager class,
person = models.ForeignKey('Person')
This means that person and manager show a "1: many" relationship. (The same person may become a manager in a different department several times!)
(※Caution: Starting with Django 2.0, ForeignKey requires the on_delete argument. Reference: https://qiita.com/lemmy/items/5fa7f6e5ca29d2446174 )
Also,
#Department constant
DEP_ACCOUNTING = 0 #accounting
DEP_SALES = 5 #Sales
DEP_PRODUCTION = 10 #Manufacturing
DEP_DEVELOPMENT = 15 #development of
DEP_HR = 20 #human resources
DEP_FIN = 25 #Finance
DEP_AFFAIRS = 30 #General affairs
DEP_PLANNING = 35 #Planning
DEP_BUSINESS = 40 #business
DEP_DISTR = 45 #distribution
DEP_IS = 50 #Information system
The method of setting constants is often used.
The numbers are skipped so that you can handle when you want to put something in between.
When you create a new model (class) or change the attributes in the model, you need to reflect the change in the database table.
Now, execute the following command from ** master directory **.
$ python manage.py makemigrations
$ python manage.py migrate
The changes will now be reflected in the database.
SQLite is used by default in Django, but I usually use MySQL. The database around here will be a long story, and development can be done without much concern, so I will ignore it in this article.
Let's create data based on this model.
For example, when you're messing with the database, go to Django's Shell.
Execute the following command from ** master directory ** to see it.
$ python manage.py shell
I think the screen will look like this! (The smile mark and the current GitHub branch name are displayed on the right is because you are changing the terminal from bash to zsh. You can see the command break and the current branch name. It's very convenient, so refer to this article Please change it!)
You're now in Django's Shell! I will create the data here.
I made the place of origin and gender quite appropriately.
import datetime
import pytz
from manager.models import Person, Manager, Worker
for i in range(200):
birthday = datetime.datetime(year=1980 + i % 20, month=1 + i % 12, day=1 + i % 28, tzinfo=pytz.timezone('Asia/Tokyo'))
Person.objects.create(name="person{}".format(i), birthday=birthday, sex=Person.MAN, address_from=Person.TOKYO, current_address=Person.TOKYO, email="person{}@gmail.com".format(i))
First, create data based on Person.
I will omit the datetime and pytz.
There are two ways to create an object.
1) MODEL_NAME.objects.create(kwargs)
2) obj = MODEL_NAME(kwargs)
obj.save()
# MODEL_NAME is the name of the model class
#ksargs is a keyword argument
is.
The create function even saves it to the database.
By the way, to delete the created model instance (individual data), do as follows.
obj.delete() #obj is an instance
Feel free to create data like this! (I made 1200 people by changing their place of origin and gender)
About the contents of range
range(200)
range(200, 300)
range(300, 400)
...
If you change it like this, you don't have to cover your name or email address.
We will create not only Person but also Manager linked to Person.
dep_list = [Manager.DEP_ACCOUNTING, Manager.DEP_SALES, Manager.DEP_PRODUCTION, Manager.DEP_DEVELOPMENT, Manager.DEP_HR, Manager.DEP_FIN, Manager.DEP_AFFAIRS, Manager.DEP_PLANNING, Manager.DEP_BUSINESS, Manager.DEP_DISTR, Manager.DEP_IS]
for i in range(1, 201):
p = Person.objects.get(id=i)
joined_date = datetime.datetime(year=2005 + i % 10, month=1 + i % 12, day=1 + i % 28, tzinfo=pytz.timezone('Asia/Tokyo'))
Manager.objects.create(person=p, department=dep_list[i % 11], joined_at=joined_date)
There are several ways to get a Person object from a database (see below), but here we use one of them, get.
I am creating a Manager that is associated with each Person instance whose id is 1 to 200.
Workers made the same with the remaining 1000 people.
for i in range(201, 1201):
p = Person.objects.get(id=i)
m = Manager.objects.get(id=1 + i % 200)
joined_date = datetime.datetime(year=2005 + i % 10, month=1 + i % 12, day=1 + i % 28, tzinfo=pytz.timezone('Asia/Tokyo'))
Worker.objects.create(person=p, manager=m, joined_at=joined_date)
The get function has a weakness. The point is that when an instance (object) that meets the conditions is not found, an error (ObjectDoesNotExist) that is not an HTTP error is returned.
In other words, when you type in a strange URL, you will get an error, which is inconvenient (there are some security issues).
Here, I used the get function on the assumption that the object always exists if the id is in this range, but usually when I get the object in views.py etc., I use the get_object_or_404
function.
views.py
from django.shortcuts import get_object_or_404
get_object_or_404(Person, id=20)
Use it like this.
This will return an HTTP 404 error even if the object doesn't exist, so you can display it like Page Not Found
. (You can also create your own page not found screen and display it every time you get a 404)
This is safe for both the purpose you saw and the security.
Therefore, you can use the get function that you can easily apply under the premise that "an object always exists", but if you want to get one object in other situations, use the get_object_or_404 function.
Next, write a view and display the page!
Before writing the view, write ʻurls.py`.
urls.py
from django.conf.urls import url
from django.contrib import admin
import manager.views as manager_view
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^worker_list/', manager_view.WorkerListView.as_view()) #Combine URL and View!
]
He was finding a View that matched the URL.
First, we will create a page that displays a list of workers, so we combine the URL base_url / worker_list /
with the View WorkerListView
!
Next, write a View.
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import TemplateView
from manager.models import *
class WorkerListView(TemplateView):
template_name = "worker_list.html"
def get(self, request, *args, **kwargs):
context = super(WorkerListView, self).get_context_data(**kwargs)
return render(self.request, self.template_name, context)
View was a mixture of data and templates.
Here, first, let's display only the template without extracting the data.
manager
- templates
- worker_list.html
Create a folder called templates
and a file called worker_list.html
so that the hierarchy is as follows.
By doing this, Django will recognize that worker_list.html
is a template.
To briefly explain the contents of the get function, it is like creating a container for data called context
and mixing the template and context with the render function (also request).
Keep the html file simple as follows.
worker_list.html
It Works!!
First, launch the Django server.
Execute the following command from the master directory
.
$ python manage.py runserver 8000
You don't have to add the 8000
at the end.
(I just wanted to say that you can specify the port number at the end!)
Let's make a request with the url we created earlier.
You can now display it!
I skipped the following two points.
--Getting data with View --Making HTML gorgeous
Let's do these two points.
views.py
def get(self, request, *args, **kwargs):
context = super(WorkerListView, self).get_context_data(**kwargs)
workers = Worker.objects.all() #Get the object from the database
context['workers'] = workers #Put in a container
return render(self.request, self.template_name, context)
When retrieving the database, write like this.
workers = Worker.objects.all()
The meaning is "take all the objects associated with the Worker model".
You can take some instead of all.
workers = Worker.objects.filter(person__sex=Person.MAN)
Then you will only get workers whose gender is male.
person__sex
means the sex attribute of the Person object in the person attribute of the worker (complex in words? Lol).
When you refer to a constant in another class, like Person.MAN
, you need to give it a class name (which is the basis of Python!).
Also,
context['workers'] = workers
By doing so, the variable workers
will be enabled in the html file!
(The content of [''] is the variable name that can be used in the html file.)
Let's display the workers in a tabular format.
worker_list.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Worker List</title>
</head>
<body>
<table>
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>sex</th>
<th>birthday</th>
</tr>
</thead>
<tbody>
{% for worker in workers %}
<tr>
<td>{{worker.id}}</td>
<td>{{worker.person.name}}</td>
<td>{{worker.person.sex}}</td>
<td>{{worker.person.birthday}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
Django provides a template language so that you can (slightly) use Python in your HTML files. Build in tamplate tags and filters
here,
{% for worker in workers %}
{% endfor %}
Is that!
You can use workers
here because you put it in context
in View!
Other,
--{% block variable%} {% endblock%}
like {% block body%} {% endblock%}
--{% load variable%}
--{% if condition%} {% else%} {% endif%}
I often use such things! (Let's actually use it below!)
CSS and JavaScript are quite annoying to write in full, so I will include Bootstrap. * Bootstrap page
It's easy because it originally wrote CSS and JavaScript.
Here we use SB admin2
. (Very versatile!)
Download from the red circle.
Unzip the Zip file and copy the files inside to / static / bootstrap /
.
Then delete everything except the folders named dist
, js
, vendor
.
I feel like this.
Load these files from HTML.
However, it is troublesome to write or copy link or script in the head
element every time.
So, create an html file that will be the base and extend it (it's hard to understand if it's written ?? lol).
Create base.html
under/ manager / templates /
.
base.html
<!DOCTYPE html>
<html lang="ja">
<head>
{% load staticfiles %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>{% block title %}{% endblock %}</title>
<link href="{% static 'bootstrap/vendor/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<link href="{% static 'bootstrap/vendor/metisMenu/metisMenu.min.css' %}" rel="stylesheet">
<link href="{% static 'bootstrap/dist/css/sb-admin-2.css' %}" rel="stylesheet">
<link href="{% static 'bootstrap/vendor/font-awesome/css/font-awesome.min.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'manager/css/structure.css' %}" rel="stylesheet" type="text/css">
<script type="text/javascript" src="{% static 'bootstrap/vendor/jquery/jquery.min.js' %}"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.0/jquery-ui.min.js"></script>
<script src="{% static 'bootstrap/vendor/bootstrap/js/bootstrap.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/metisMenu/metisMenu.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/datatables/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/datatables-plugins/dataTables.bootstrap.min.js' %}"></script>
<script src="{% static 'bootstrap/vendor/datatables-responsive/dataTables.responsive.js' %}"></script>
<script src="{% static 'bootstrap/dist/js/sb-admin-2.js' %}"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div id="wrapper">
<nav class="navbar navbar-default navbar-static-top manager-nav no-margin" role="navigation">
<div class="navbar-header">
<a class="navbar-brand">gragragrao Company</a>
</div>
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li><a href="/worker_list/"><i class="fa fa-bar-chart" aria-hidden="true"></i>Worker list</a></li>
</ul>
</div>
</div>
</nav>
{% block body %}
{% endblock %}
</div>
</body>
</html>
For {% block title%} {% endblock%}
and {% block body%} {% endblock%}
, substitute the script contained in the same block in the extended HTML file as it is. Is to do.
Extend this to create worker_list.html
!
worker_list.html
{% extends "base.html" %}
{% block title %}Worker List{% endblock %}
{% load staticfiles %}
{% block body %}
<div id="wrapper">
<div id="page-wrapper">
<div class="row">
<div class="col-lg-6 full-width margin-top-20percent" >
<div class="panel panel-default full-width">
<div class="panel-heading">
Edit Help
</div>
<div class="panel-body full-width full-height">
<table id="worker-list-table" class="table table-striped table-bordered table-hover dataTable no-footer dtr-inline full-width">
<thead>
<tr>
<th>ID</th>
<th>name</th>
<th>sex</th>
<th>birthday</th>
</tr>
</thead>
<tbody>
{% for worker in workers %}
<tr>
<td>{{worker.id}}</td>
<td>{{worker.person.name}}</td>
<td>{{worker.person.sex}}</td>
<td>{{worker.person.birthday}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$('#worker-list-table').DataTable({
responsive: true,
//Disable sort function
ordering: false,
//Change the number of pages displayed
displayLength: 20,
});
});
</script>
{% endblock %}
--{% extends filename%} to extend the original file --{% load staticfiles%} loads static files under / static /. (It cannot be read without this!)
However, what is static files
as it is? So let's tell Django what it is with setting.py
.
Add the following somewhere in the setting.py file.
setting.py
# Static file settings
STATIC_ROOT = os.path.join(BASE_DIR, 'assets')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
After that, I will prepare a little CSS.
structure.css
/* ---------------------------------------------------------- */
/* general */
/* ---------------------------------------------------------- */
.full-height {
height: 100%;
}
.full-width {
width: 100%;
}
.margin-top-20percent {
margin-top: 20px;
}
.no-margin {
margin: 0 !important;
}
In base.html
, this file is called as follows.
<link href="{% static 'manager/css/structure.css' %}" rel="stylesheet" type="text/css">
Files under static can be called like this!
So, let's put structures.css
under/ static / manager / css /
!
This is complete for the time being! !!
If it doesn't work, I would appreciate it if you could report it in the comments.
Launch Django's server from your terminal and see what the page looks like!
From the master directory
, do the following!
$ python manage.py runserver
This will come out below
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Let's connect to http://127.0.0.1:8000/worker_list/
from your browser!
It turned out to be something like this!
It's been long, so I'll leave it around here this time!
From now on, let's extend this app and master Django!
It was helpful! If you like it, please like it!
Recommended Posts