I usually use Laravel (PHP) or ASP.NET MVC (C #), but sometimes I remember when using Django.
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.
Because you are using another framework? ?? ?? People who are already using other frameworks will find it easier to understand the difference in advance.
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.
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.
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.
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.
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
Before we get into specific coding, we will create and configure the 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
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.
Now, let's make the settings to use the database. Django uses SQLite by default, but I would like to use MySQL.
Next, install the packages required to use MySQL from Python. There seem to be various types, but I will use PyMySQL.
pip install PyMySQL
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.
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 |
+----------------------------+
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.
Now that the settings related to the entire project have been completed, create an application. Here, we will create an application named sample.
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/
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',
]
It's finally time to start coding. You can write anything, but first we will start with 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
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 | |
+-------+--------------+------+-----+---------+----------------+
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.
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.
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.
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.
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!")
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.
Now that we know the relationship between views.py and urls.py, let's define a template (HTML) and use it.
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. 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.
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?
Now, let's display the data stored in the database.
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 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.
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.
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).
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
}
]
}
Now that I understand the basic operation, I think the next step is I want to try CRUD.
Recommended Posts