[PYTHON] Development digest with Django

I usually use Laravel (PHP) or ASP.NET MVC (C #), but sometimes I remember when using Django.

What you want to check

What I want to know is

I said that. In that sense, it's mostly covered in the article here (thank you), but it's a little different from my needs. There are also, so I will try to summarize it in my own way.

What other framework users are confused about

Because you are using another framework? ?? ?? People who are already using other frameworks will find it easier to understand the difference in advance.

MTV model instead of MVC

Django uses an MTV model, not an MVC. However, it seems that there is no need for a new concept because the image is that the name of the VC part is different rather than the model is different.

Is the correspondence between MVC and MTV as follows?

The act of messing with Viwe (views.py) is like messing with the Controller in MVC, and Template is like messing with the View (HTML description) of MVC.

There is a concept of project and application

It seems that the big concept of a project includes an application.

The settings common to the whole are set in the scope of the project, and the settings and description of each application are images made by the application.

Personally, I got the impression that the relationship between the Visual Studio solution and the project.

The directory structure is a little confusing (for explanation)

I think this is a matter of familiarity, but for example, if you create a project named django_test, the following files will be generated.

django_test/
    manage.py
    django_test/
        __init__.py
        settings.py
        urls.py
        wsgi.py

A directory that holds the entire project (top-level django_test) and a subdirectory of the same name that holds the related files for the project are generated, so when you simply say django_test directory, it tends to be difficult to tell which django_test directory. ..

The operation in this article uses the top-level django_test as the calendar directory.

form (automatic generation) is a little special

Although not covered in this article, Django has a culture of "automatically generating forms," so there are Form and ModelForm classes to do that. What if you don't have the prior knowledge of "automatically generate a form"? ?? ?? It will become.

Development environment

Let's assume that you already have a Python environment (3.x). I create and use a virtual environment with venv on Mac. Please see here for environment setup.

The version of python is 3.6.1, and the result of pip freeze is as follows.

pip freeze
Django==1.11
django-bootstrap-form==3.2.1
PyMySQL==0.7.11
pytz==2017.2

Preparation and confirmation

Before we get into specific coding, we will create and configure the project.

Creating a project

First, create a Django project. When you execute the following command, a directory called django_test will be created and the necessary files will be generated.

django-admin.py startproject django_test

Check if it works for the time being

At this point, let's check if it works for the time being. Start the development server.

python manage.py runserver

Django uses manage.py as various control commands. It feels like Laravel's artisan.

After starting, try accessing the following URL.

http://localhost:8000

It's okay if [It worked!] Appears on the screen that doesn't look like it.

I can't migrate! !! !! Warning will be displayed, but there is no problem as it will be dealt with later. If you are interested, please execute the following migrate first.

When the confirmation is completed, use Ctr + C to terminate the development server.

Database settings

Now, let's make the settings to use the database. Django uses SQLite by default, but I would like to use MySQL.

Installation of required packages

Next, install the packages required to use MySQL from Python. There seem to be various types, but I will use PyMySQL.

pip install PyMySQL

Edit settings.py

Once the package is in, set the database access information. In Django, set the database connection information in settings.py under the project directory (django_test in this case).

Describe DATABASES as follows. Change the database name and access information as appropriate.

django_test/settings.py


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'djangodb',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '',
        'PORT': '',
    }
}

Of course, it is assumed that MySQL is running and a database called djangodb has been created.

Also, add the following description at the top of settings.py so that the project loads the PyMySQL package.

settings.py


import pymysql
pymysql.install_as_MySQLdb()

Where should I really write it? Please let me know.

Perform migration

Now that you have set the database connection information, try migrating.

python manage.py migrate

If the database is set up properly, it should work. If there is an error, check various settings. When executed correctly, it seems that the following table was created. There aren't many.

+----------------------------+
| Tables_in_djangodb         |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+

Also play with LANGUAGE_CODE and TIME_ZONE.

While playing with settings.py, play with other settings as well.

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

At this point, run runserver and check http: // localhost: 8000 again and the message should be in Japanese.

Create an application

Now that the settings related to the entire project have been completed, create an application. Here, we will create an application named sample.

Creating an application

Execute the following command to create an application.

python manage.py startapp sample

When executed, a directory called sample will be added, and application-related files will be generated under it. The hierarchical structure should look like this:

django_test/
    sample/
        __init__.py
        admin.py
        apps.py
        migrations/
            __init__.py
        models.py
        tests.py
        views.py
    manage.py
    django_test/

Add application

Once you've created your application, project it? Add it to INSTALLED_APPS in settings.py so that it can be recognized. I think this area is a "magic" type, so I will proceed without complaining.

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

Model definition

It's finally time to start coding. You can write anything, but first we will start with the model.

Describe the model

Describe the model in models.py generated under sample.

Here, let's define a Member model that imagines the storage of member information. This description is used as table generation information when generating a migration file.

There seems to be a way to use an existing table.

sample/models.py


class Member(models.Model):
	name = models.CharField('Full name', max_length=255)
	email = models.CharField('E-Mail', max_length=255)
	age = models.IntegerField('age', blank=True, default=0)

	def __str__(self):
		return self.name

Creating and running a migration file

Now, generate a migration file and perform migration. Generate a migration file by specifying the name of the application that generated the model.

python manage.py makemigrations sample
python manage.py migrate

Do this every time you make changes to your model.

It looks like the migration was successful, so I'm looking at the generated table. Apparently, the table name is named applicationname_tablename (rather than plural).

+----------------------------+
| Tables_in_djangodb         |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| sample_member              |
+----------------------------+

Let's take a look at the contents.

It seems that the default value is not 0, but I don't care about the details and proceed.

+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | NO   |     | NULL    |                |
| email | varchar(255) | NO   |     | NULL    |                |
| age   | int(11)      | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+

Use the management site

Django doesn't have a scaffold, but it has a pre-defined management site to manage your model. You can insert the data directly into the DB, but since it's a big deal, enable the management site and try using it.

There is also a mechanism called Fixture that inputs data.

Creating a login user

If you go to http: // localhost: 8000 / admin without doing anything, you can access the administration site itself, but it is not available because the user and password to log in are not defined. So generate it.

If the development server is not running, start it with runserver.

python manage.py createsuperuser

Please set your user name, email address and password as needed. When you're done, try logging in with the generated user and password.

Add a managed table

When I log in to the management site, there are items that say groups and users, but I can't find Member. It seems that you need to register as a management target to make it a management target.

Make admin.py under sample as follows.

sample/admin.py


from django.contrib import admin
from sample.models import Member

# Register your models here.
admin.site.register(Member)

When you log in (update) to the management screen again, the description "members" is added. Now, let's add some data because we want to use it for display later.

Let's display it (preparation)

Before displaying the registered data, let's investigate how it is displayed. For display

It seems that it is common to follow the flow, but first, let's use only View and routing definition without using template.

Display mechanism 1 (Try to display something for the time being)

Play with views.py

Now let's define the View. Specifically, add the description to views.py under sample. For the time being, I wrote a method called index that directly returns "Index!".

sample/views.py


from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.
def index(request):
	#Returns a string for the time being.
	return HttpResponse("Index!")

Define routing

Then map the URL and method. Note that the definition of routing in Django does not describe everything in one file.

It's like a manner, so follow it.

Then, generate urls.py under sample and describe it as follows.

sample/urls.py


from django.conf.urls import url
from sample import views

urlpatterns = [
	url(r'^members/$', views.index, name='index'),
]

The route (URL to map) seems to be written in a regular expression. It's annoying when it comes to trouble, but it's certain when it comes to certainty. The first r'' seems to mean that special characters such as \ are also treated as ordinary characters in''.

Now that the description in the application is finished, write the following in urls.py under the solution (django_test).

urls.py


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

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^sample/', include('sample.urls', namespace='sample'))
]

Now that the definition is complete, runserver and try accessing the URL below.

http://localhost:8000/sample/index

If the message "Index!" Is displayed, it is OK.

Display mechanism 2 (Try using a template)

Now that we know the relationship between views.py and urls.py, let's define a template (HTML) and use it.

Create a common file

In Django, the common template is

project_name/application_name/templates/base.html

It seems to be arranged according to the rule. here,

django_test/sample/templates/base.html

Generate and describe the file. The templates directory does not exist, so create it.

I use Bootstrap a lot, so I modified the Bootstrap sample a bit (changed to use a CDN) to make it a common template.

sample/templates/base.html


{% load staticfiles %}
<!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">
    <title>{% block title %}My books{% endblock %}</title>
    <!-- Bootstrap -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      {% block content %}
        {{ content }}
      {% endblock %}
    </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  </body>
</html>

As you can see, in the above description,

<title>{% block title %}My books{% endblock %}</title>

<div class="container">
      {% block content %}
        {{ content }}
      {% endblock %}
</div>

The parts are dynamically replaced as needed.

You can also define a directory to put static contents, but I will omit it here. In that sense, I don't think the description {% load staticfiles%} is necessary in this range.

Describe each page (index.html)

Describe each page. In Django, it seems that there is no strict association between View (controller) name and folder name for other MVC frameworks, but here I create a directory called members under templates and create index.html under it ・ Describe.

Let's read only base.html and describe only the content to be mapped to the block defined in base.html for the time being.

sample/templates/members/index.html


{% extends "base.html" %}

{% block title %}
Scheduled to display a list
{% endblock title %}

{% block content %}
<h1>Content for the time being</h1>
{% endblock content %}

In Django's template system,

{% block block_name %}{% endblock block_name %}

It seems that dynamic display is realized by defining a block with the rule and preparing a variable corresponding to block_name.

Change the description of views.py to go to the individual base

Now, change the description of views.py so that you can see the created index.html instead of the description that directly responded to "Index!".

sample/views.py


def index(request):
	# return HttpResponse("Index!")
	return render(request, 'members/index.html')

When editing is complete, runserver and

http://localhost:8000/sample/members/

Please access to check if it is displayed correctly. Is the title replaced correctly?

Try to display the data

Now, let's display the data stored in the database.

Edit views.py again

Edit views.py and change the description to get the value from the database and return it to the template.

sample/views.py


from django.shortcuts import render
from django.http import HttpResponse

from sample.models import Member

# Create your views here.
def index(request):
	# return HttpResponse("Index!")
	members = Member.objects.all().order_by('id') #Get value
	return render(request, 'members/index.html', {'members':members}) #Pass a value to Template

Edit index.html

Edit the display side as well. Let's display the received data in table format.

index.html


{% extends "base.html" %}

{% block title %}
Scheduled to display a list
{% endblock title %}

{% block content %}
<h3>List display</h3>
<table class="table table-striped table-bordered">
	<thead>
		<tr>
			<th>ID</th>
			<th>Full name</th>
			<th>E-Mail</th>
			<th>age</th>
		</tr>
	</thead>
	<tbody>
		{% for member in members %}
		<tr>
			<td>{{ member.id }}</td>
			<td>{{ member.name }}</td>
			<td>{{ member.email }}</td>
			<td>{{ member.age }}</td>
		</tr>
		{% endfor %}
	</tbody>
</table>
{% endblock content %}

It's not particularly difficult, but the loop part,

{% for member in members %}
<tr><td>What to loop</td></tr>
{% endfor %}

It is described as.

Please check and see when you are done.

Try to return JSON

Finally, let's create a Web API. The point is the response in json. Unfortunately with Django? It seems that one effort is required.

In addition, is it full-scale? It seems that you can also use Django Rest Framework for the API.

Description in views.py

Add the following method to sample / views.py. I chose a method called api here (it's not a good name).

It seems that you should respond after storing the acquired data in OrderedDict.

OrderedDict, as the name implies, is an ordered dictionary type, and in a normal dictionary type, the order of data will be out of order, so it seems that it is stored once in the OrderedDict type.

sample/views.py


def api(request):
	members = []
	for member in Member.objects.all().order_by('id'):
		member_dict = OrderedDict([
				('id',member.id),
				('name',member.name),
				('email',member.email),
				('age',member.age),
			])
		members.append(member_dict)

	data = OrderedDict([
			('status','ok'),
			('members',members),
		])
	
	json_str = json.dumps(data, ensure_ascii=False, indent=2)
	return HttpResponse(json_str, content_type='application/json; charset=utf-8')

It does not use a template and responds directly in views.py. I also added something like status to the top level (because I often use it personally).

Add route

Map the URL that corresponds to the api method you added. For the time being, I did the following.

from django.conf.urls import url
from sample import views

urlpatterns = [
	url(r'^members/$', views.index, name='Index'),
	url(r'^members/api/$', views.api, name='Api'),
]

Then runserver and

http://localhost:8000/members/api/

Please visit to see if the expected json comes back.

The following json is back.

{
  "status": "ok",
  "members": [
    {
      "id": 1,
      "name": "hoge",
      "email": "[email protected]",
      "age": 20
    },
    {
      "id": 2,
      "name": "foo",
      "email": "[email protected]",
      "age": 40
    }
  ]
}

from now on

Now that I understand the basic operation, I think the next step is I want to try CRUD.

Recommended Posts

Development digest with Django
Test Driven Development with Django Part 3
Test Driven Development with Django Part 4
Test Driven Development with Django Part 6
Test Driven Development with Django Part 2
Test Driven Development with Django Part 1
Test Driven Development with Django Part 5
Internationalization with django
CRUD with Django
First Django development
Application development using SQLite with Django (PTVS)
Authenticate Google with Django
Django 1.11 started with Python3.6
Upload files with Django
Build Django + NGINX + PostgreSQL development environment with Docker
Output PDF with Django
Build the fastest Django development environment with docker-compose
Markdown output with Django
Use Gentelella with django
Twitter OAuth with Django
[Python] Build a Django development environment with Docker
Getting Started with Django 1
Send email with Django
File upload with django
Build a Django development environment with Doker Toolbox
Use LESS with Django
Pooling mechanize with Django
Use MySQL with Django
[Memo] Django development environment
Start today with Django
Getting Started with Django 2
Build a development environment with Poetry Django Docker Pycharm
Articles that enable system development with Django (Python) _Introduction
Do Django with CodeStar (Python3.6.8, Django2.2.9)
Get started with Django! ~ Tutorial ⑤ ~
Minimal website environment with django
Create an API with Django
Django development environment construction memo
Do Django with CodeStar (Python3.8, Django2.1.15)
Deploy Django serverless with Lambda
Python3 + Django ~ Mac ~ with Apache
Getting Started with Python Django (1)
Web application development with Flask
Create a homepage with django
Get started with Django! ~ Tutorial ④ ~
Getting Started with Python Django (4)
Web application creation with Django
Getting Started with Python Django (3)
Combine FastAPI with Django ORM
Get started with Django! ~ Tutorial ⑥ ~
Django environment development on Windows 10
Save tweet data with Django
Do AES encryption with DJango
Getting Started with Python Django (6)
Combine two images with Django
Getting Started with Django with PyCharm
Real-time web with Django Channels
django project development environment construction
Double submit suppression with Django
Django REST framework with Vue.js
Use prefetch_related conveniently with Django