使用Python的Django创建第一个网页
这是一张关于Django命令的备忘录或复制粘贴用的参考纸。
由于无论做多少次,我都记不住步骤,所以我会一边参照Qiita的文章一边进行。
这是一个用于自用的,复制粘贴命令模板以进行再现。
我会特别注意让读者在阅读时能够通过命令和图像来想象操作的过程。
先决条件
Ubuntu 20.04。
Python 3已预先安装。
但是提示说pip没有安装。
这是我作为初学者学习编程的笔记,我经常复制黏贴,所以有些地方我还不太明白。
由于类视图很困难,所以我采用了函数视图来编写。
准备虚拟环境
由于使用Python,我们将创建一个虚拟环境(保存Python库的位置)。
这次我们将使用virtualenv。
$ sudo apt install python3-pip
$ pip3 install virtualenv
我创建一个项目文件夹,并设定一个存储库的位置。
$ mkdir testsite
$ cd testsite
$ virtualenv virtualenv
为了能够复制库的依赖关系,我们需要创建一个空的requirement.txt文件。
$ touch requirement.txt
文件数量是最小必需的。
目录结构如下所示。
testsite
├── virtualenv
└── requirements.txt
在虚拟环境中进行安装。
为了在虚拟环境virtualenv中安装Django,需要启动虚拟环境。
因为我曾经忘记这一步并将其安装在本地环境中,导致环境混乱,因此写了这篇文章来阐述此步骤。
因为我经常忘记点(.),所以我会在代码中记住它。
在当前的终端(.)下执行虚拟环境。
$ . virtualenv/bin/activate # source virtualenv/bin/activate
(virtualenv)MyName@MyPC:~/testsite$
如果是这样的话,我正在使用虚拟环境。
我猜想,如果尝试运行pip3 list,可能会提示没有库存在。
$ pip3 list
我们将使用pip安装库。
如果不指定版本,将安装Django3.X系列,但这里我们选择2.2系列。
$ pip3 install Django==2.2.24
暫且作為新手的我,我在這裡將練習寫進requirement.txt中。
$ pip3 freeze -l > requirement.txt
$ vi requirement.txt
Django==2.2.24
pytz==2021.1
sqlparse==0.4.1
创建项目
由于项目文件夹已经先前创建好了,所以我们需要在那里生成Django的代码。
根据官方教程的创建方法,项目文件夹名和配置目录名会变得相同,这样就不易理解。为了更清晰明了的结构,通常会使用以config为名称的配置目录。
我们可以通过在当前目录(.)创建一个名为config的配置目录来选择将当前目录作为项目文件夹。
$ django-admin startproject config .
已创建config文件夹和manage.py文件。
testsite
├── config
├── virtualenv
├── manage.py
└── requirements.txt
由于目前可以启动,作为初学者,现在就在这里启动吧。
$ python3 manage.py runserver
由于这是英语,我将其转换为日语。
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
创建认证和授权功能
在Django中,建议尽早创建自定义用户,即使这可能会变得复杂。这与Python中首先创建虚拟环境的惯例相似。创建自定义用户意味着需要创建授权和认证应用程序。由于方便的管理界面从一开始就包含在内,所以据说后来会出现奇怪的错误。
有些人也介绍了一种更简单的方法
创建自定义用户模型
虽然这次看起来麻烦,但我是从似乎也是准官方的LearnDjango.com借鉴来的
Django最佳实践:自定义用户模型
在manage.py中创建一个应用程序
据说在Django中,功能是以“app”作为单位来调用的。
为了覆盖标准的认证授权功能,我们将创建一个名为“accounts”的认证授权功能。
$ python3 manage.py startapp accounts
将数据读取到项目设置文件中。
在settings.py文件的INSTALLED_APPS列表的末尾处,添加配置以加载自己创建的accounts应用程序。
通过startapp命令创建的文件中存在一个apps.py文件,在该文件中定义了一个类,需要进行该类的加载。
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts'
将此类复制并添加
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# manage.pyで作成した認証認可アプリ
'accounts.apps.AccountsConfig', # 追加
]
听说应该按照从上到下的顺序阅读,所以我觉得把我的应用程序(功能)写在最底下可能更好吧。
创建定制用户
我会做出来,但是什么都不会做。我会跳过;
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
pass
def __str__(self):
return self.username
覆写认证用户
在startapp中创建的accounts的CustomUser类位于models.py中,但请注意不要写成accounts.models.CustomUser。
可以在settings.py的末尾添加注释并进行补充。
# 管理画面認証ユーザーの設定
AUTH_USER_MODEL = 'accounts.CustomUser'
添加用户,覆盖注册表单
我听说在管理界面中经常使用,因此我会遵从,因为这让我感到害怕。
$ touch accounts/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = ('username', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('username', 'email')
提交到管理界面
这涉及到模型自身和表单的注册以及界面显示的设置。
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username',]
admin.site.register(CustomUser, CustomUserAdmin)
将数据存入数据库
$ python3 manage.py makemigrations accounts
$ python3 manage.py migrate
终于成功迁移到新的环境了。因为迁移完成,所以已经创建了db.sqlite3文件,我来看看。
testsite
├── accounts
├── config
├── db.sqlite3
├── manage.py
├── requirements.txt
└── virtualenv
文件数量逐渐增加了一些。
创建页面显示功能
在这里终于到了正题,开始第一个网页的制作。
关于复数或app.apps这样复杂的命名规则,我不太清楚,但会用app进行制作。
开始应用
$ python3 manage.py startapp app
testsite
├── accounts
├── app
├── config
├── db.sqlite3
├── manage.py
├── requirements.txt
└── virtualenv
INSTALLED_APPS = [
...,
# manage.pyで作成した認証認可app
'accounts.apps.AccountsConfig',
# manage.pyで作成したページ表示app # 追加
'app.apps.AppConfig', # 追加
]
设定
与MVC模式类似,Django的MTV模式也不会在一个文件中进行显示。
需要编辑三个文件来创建页面。
当访问URL时,按顺序执行服务器处理并返回HTML,然后显示给用户。
按照urls.py -> views.py -> HTML文件的顺序进行编写可能更容易理解。
不过,设置还没有完成。
指定要加载模板的位置
在当前目录下创建一个名为templates的目录。
$ mkdir templates
我会在settings.py文件中的TEMPLATES的DIRS列表中告诉您新建模板的位置。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates")], # ディレクトリ直下の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',
],
},
},
]
将路径定向到配置文件
由于配置,访问仅限于config.py的urls.py。
由于我们将在app中创建urls.py文件,因此只需先编写加载设置。
from django.contrib import admin
from django.urls import path
from django.urls import include # 追加
urlpatterns = [
path('admin/', admin.site.urls),
path('', include(app.urls)), # rootパスにmanage.pyで作成したapp内のurls.pyをincludeする。
]
现在开始创建 urls.py。
创建urls.py文件
我将创建一个包含要包括的URL的列表,并逐一书写。
touch app/urls.py
urlpatterns = []
现在,尽管还是空的,但是已经可以进行读取设定了。
创建页面
我会同时创建三个文件,并逐步显示HTML。
我会在先前的空urls中指示查看views中的top函数。
from django.urls import path
from app import views
urlpatterns = [
path('', views.top, name='top'),
]
在视图中添加了一个名为”top”的函数。
“top”函数会引用模板文件夹中的”app/top.html”。
from django.shortcuts import render
def top(request):
context = {}
return render(request, 'app/top.html', context)
mkdir templates/app
touch templates/app/top.html
<h1>top.htmlのページ</h1>
我想要引入BootStrap,试着制作一个漂亮的首页。
引入BootStrap
$ pip3 install django-bootstrap4
INSTALLED_APPS = [
...,
# Bootstrapの導入
'bootstrap4',
]
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
...,
],
# Bootstrapの導入 # 追加
'builtins': [ # 追加
'bootstrap4.templatetags.bootstrap4'], # 追加
},
},
]
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
<div class="jumbotron">
<h1 class="display-4">Hello, world!</h1>
<p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>
<hr class="my-4">
<p>It uses utility classes for typography and spacing to space content out within the larger container.</p>
<p class="lead">
<a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a>
</p>
</div>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" rel="stylesheet">
<script crossorigin="anonymous" integrity="sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script crossorigin="anonymous" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
只是通过CDN获取。
暂时将这个也保存为依赖关系。
$ pip3 freeze -l > requirements.txt
$ cat requirements.txt
beautifulsoup4==4.9.3
Django==2.2.24
django-bootstrap4==3.0.1
pytz==2021.1
soupsieve==2.2.1
sqlparse==0.4.1