该笔记使用 Python 3.9.12
Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架,具有强大的数据库功能和强大的后台功能
在终端中键入下面命令安装:
$ pip install Django
···
···
···
Installing collected packages: sqlparse, asgiref, Django
Successfully installed Django-4.1.1 asgiref-3.5.2 sqlparse-0.4.2
查看当前 Django 版本:
$ django-admin --version
4.1.1
安装完成 Django 后,就可以开始使用管理工具 django-admin 了
$ django-admin
Type 'django-admin help ' for help on a specific subcommand.
Available subcommands:
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
optimizemigration
runserver
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
先说个目前看起来可能关系不大的问题。
(限 Python 3.3 及以上版本,不在该版本限制内直接看下面正文。)
实际开发过程中往往会存在多个 Python 项目(学习过程中可能也有,但是吧,自己学习的时候比较有时间折腾)每个项目所需的 Python 版本可能不一致,比如 Python 2.X、Python 3.X,每个项目所需的依赖包也可能不一致,比如 A 项目只要 Selenium 相关依赖包,B 项目只要 Appium 相关依赖包,即便不同项目用同一个依赖包,但依赖包版本可能不一致。
这个时候把不同项目所需要的环境隔离开来是很有用的。
恰好 Python 自带的轻量级虚拟环境 venv 可以满足这种需求。使用方法如下:
新建一个目录作为项目的容器:
$ mkdir my_note
$ cd my_note
在新建的目录中建立虚拟环境,并激活它,这里 ll_env 是当前环境的名称:
$ python -m venv ll_env
$ source ll_env/bin/activate
然后就可以在这个激活的这个虚拟环境中开始一个项目辣~
如果想退出虚拟环境,在终端输入如下命令即可:
$ deactivate
如果这个项目废弃终止不想学了,直接把整个目录删掉就可以辣~
具体教程可以查看 venv — Creation of virtual environments
这里创建一个名为 my_note 的项目,用于分类保存不同的学习笔记。
$ django-admin startproject my_note .
使用 startproject 子命令来创建一个项目,这里 my_note 是当前项目的名称,点号 (.) 指定项目创建路径为当前路径。
使用下面命令可以查看更为详细的子命令使用语法:
$ django-admin help startproject
新建项目后,当前路径新增一个名为 manage.py 的文件和一个名为 my_note 的文件夹。
$ ls
manage.py my_note
其中,manage.py 是一个命令行工具,可让项目所有者以各种方式与该 Django 项目进行交互。
文件夹 my_note 是当前项目的容器,其中又包含如下五个文件:
$ ls my_note
__init__.py settings.py wsgi.py
asgi.py urls.py
各文件分工大致如下:
my_note | 项目容器 |
---|---|
init_.py | 空文件,告诉 Python 该目录是一个 Python 包 |
asgi.py | (Asynchronous Server Gateway Interface) 异步服务器网关接口 |
settings.py | Django 项目的配置文件,指定 Django 如何与系统交互以及如何管理项目 |
urls.py | 该 Django 项目的 URL 声明,一份由 Django 驱动的网站"目录",告诉Django应创建哪些网页来响应浏览器请求 |
wigs.py | (web server gateway interface) Web 服务器网关接口,帮助Django 提供它创建的文件 |
在终端键入如下命令启动该项目服务:
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
September 09, 2022 - 06:02:21
Django version 4.1.1, using settings 'my_note.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
通过输出可以看到, django 默认使用 8000 端口,如果出现如下端口占用提示:
Error: That port is already in use.
通过如下方式指定可用的端口即可(可以通过不断增加端口值来尝试到底哪个值是可用的):
$ python manage.py runserver 8001
输出的最后一句提示终止服务器的指令 Ctrl + c:
...
Quit the server with CONTROL-C.
成功启动项目服务后,先不急于关闭服务。在浏览器中打开 127.0.0.1:8000,检查是否能正常访问,这里我打开的网页显示如下:
如果成功打开 Django 页面,则表示目前服务是正常的,如果无法打开,删除当前目录再依据上述步骤重走一遍。
Django 的特点之一,是有强大的数据库功能,它采用的是 MVT 的软件设计模式,即:
这里就先来创建一个数据库,体验一下 强大的 数据库功能。
Django 对各种数据库包括:PgSQL、MySQL、SQLite、Oracle 提供了很好的支持,这里使用 Django 默认的数据库 SQLite。
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
...
...
Applying sessions.0001_initial... OK
migrate 迁移数据库,该子命令让数据库与当前状态匹配,确保数据库结构与当前状态匹配。若数据库不存在,将新建一个数据库,用于储存项目中存在的信息。
当前 Demo 中的数据库是 db.splite3。
$ ls
db.sqlite3 manage.py my_note
$ python manage.py startapp notes
$ ls notes/
__init__.py apps.py models.py views.py
admin.py migrations tests.py
startapp 创建一个应用,并在当前目录下创建同名目录,因此需要和项目名称区分开来,否则会报错:
$ python manage.py startapp my_note
CommandError: 'my_note' conflicts with the name of an existing Python module and cannot be used as an app name. Please try another name.
查看应用目录(这里是notes/)下文件:
my_note | 应用目录 |
---|---|
admin.py | 用于自定义 Django 管理工具 |
apps.py | 主要用于左侧菜单栏展示,和排序位置 |
modes.py | 模型类,相当于数据库表 |
tests.py | Django测试文件 |
views.py | 视图类 |
回顾 MVT 设计模式,数据库与用户的交互,离不开模型的支持,因此还需要定义模型。
(为什么一定要使用视图模型?为什么用户不能直接和数据库交互?模型视图实现了数据和界面分离,使得相同的数据在多个不同的视图中进行显示成为可能,提高了灵活性和重用性。详细的知识后面再学习和补充笔记。)
Django 模型使用自带的 ORM(Object Relational Mapping 对象关系映射)实现面向对象编程语言里不同类型系统的数据之间的转换,通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。
ORM 与数据库的对应关系如下:
优点:数据库类型无关
缺点: ORM 代码转换为 SQL 语句对执行效率有一定程度影响
模型定义于 notes/models.py
$ cat notes/models.py
from django.db import models
# Create your models here.
这里首先定义一个笔记主题类:
# models.py
from django.db import models
# Create your models here.
class TopicModel(models.Model):
# 主题名称
text = models.CharField(max_length = 200)
date_added = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.text
models.Model 是 Django 的一个模型类,Django 要求所有自定义模型类都必须继承此类。这里 TopicModel 可以理解为数据库的表名,而成员变量 text、data_added 表示表字段,其字段类型分别为 Char 和 DateTime。
模型定义出来后,必须在项目中包含该应用。前面新建项目的时候,在项目容器目录 my_note 中有一个 settings.py,该文件为 Django 项目的配置文件,指定 Django 如何与系统交互以及如何管理项目。
因此修改 settings.py 文件来 告诉Django 将应用 notes 安装在项目中。
在 settings.py 中找到 INSTALLED_APPS,顾名思义,该列表告诉 Django 当前项目由哪些应用组成,在这个列表后追加上面新建的应用的名称,并保存该文件。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'notes',
]
settings.py 中还包含了很多其他的内容,后面在补充其他内容的笔记。
一切准备就绪,接下来只要让 Django 在数据库中添加 TopicModel 相关的信息即可。
$ python manage.py makemigrations notes
Migrations for 'notes':
notes/migrations/0001_initial.py
- Create model TopicModel
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, notes, sessions
Running migrations:
Applying notes.0001_initial... OK
子命令 makemigrations 为自定义的 model 类生成数据库迁移文件,以便于后面在数据库中生成数据表,最后调用 migrate 应用迁移,将迁移文件集同步到数据库中。
现在数据库中已经包含了上面定义的模型:
sqlite> .open db.sqlite3
sqlite> select tbl_name from sqlite_master where type = 'table';
django_migrations
sqlite_sequence
auth_group_permissions
auth_user_groups
auth_user_user_permissions
django_admin_log
django_content_type
auth_permission
auth_group
auth_user
django_session
notes_topicmodel
sqlite> .schema notes_topicmodel
CREATE TABLE IF NOT EXISTS "notes_topicmodel" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "text" varchar(200) NOT NULL, "date_added" datetime NOT NULL);
【总结】修改 Django 数据库结构:
首先创建一个超级管理员,方便使用超级管理员账号在 Django 管理网站上对数据库追加数据。
python manage.py createsuperuser
Username (leave blank to use 'a123'): admin
Email address:
Password:
Password (again):
Superuser created successfully.
查看数据库可以发现,Django 并不直接保存密码明文,而是保存通过密码生成的一串散列值,用户登陆的时候,通过比较用户输入生成的散列值和数据库中的值来进行身份验证。
sqlite> select * from auth_user;
1|pbkdf2_sha256$390000$jQABTD2vujvADKmyU0SIWx$MoJz6m7XYP+dNQQrxIAz0W8XxUhyI5AJL0dYmlrssWk=||1|admin|||1|1|2022-09-14 02:33:34.769381|
为了在管理网站上操作自定义数据模型,还需要将上面创建的模型注册到网站中去,实现的方法是,在应用目录 notes/ 中的 admin.py 中进行注册:
# admin.py
from django.contrib import admin
# Register your models here.
# 注意这里先导入模型类,否则会提示’NameError: name 'TopicModel' is not defined‘
from notes.models import TopicModel
admin.site.register(TopicModel)
现在,可以通过在浏览器访问 ‘http://127.0.0.1:8000/admin/’ 登录管理员账号辣~
可以看到,网页上显示了上面自定义的 TopicModels 模型:
但上面有一个问题,就是 Topic models 是根据上面定义的类名生成的,但其实并不是我想要显示的文本。
这种情况下只要在模型中加入class Meta 即可:
# models.py
from django.db import models
# Create your models here.
class TopicModel(models.Model):
# 主题名称
text = models.CharField(max_length = 200)
date_added = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.text
# ---------------- 下面是修改的部分 ----------------
# 自定义显示文本:
class Meta:
# 单数
verbose_name = 'Topic'
# 复数
verbose_name_plural = 'Topics'
Meta 类主要用来存储用于管理模型的额外信息,这里通过设置它的 verbose_name 和 verbose_name_plural,来实现自定义显示文本的效果。
因为修改了模型,因此需要再次迁移数据库,并重新启动服务:
$ python manage.py makemigrations notes
Migrations for 'notes':
notes/migrations/0002_alter_topicmodel_options.py
- Change Meta options on topicmodel
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, notes, sessions
Running migrations:
Applying notes.0002_alter_topicmodel_options... OK
¥ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
September 14, 2022 - 07:05:47
Django version 4.1.1, using settings 'my_note.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
现在,可以通过网页上的添加修改按键来添加主题,这里我随手建了两个主题:
主题有了,现在新建一个条目类,用于往主题中新增条目,新增修改模型均在 models.py 文件入手,操作同上面建立主题模型一样:
# models.py
from django.db import models
class TopicModel(models.Model):
text = models.CharField(max_length = 200)
date_added = models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.text
class Meta:
verbose_name = 'Topic'
verbose_name_plural = 'Topics'
class EntryModel(models.Model):
# 条目关联的主题
topic = models.ForeignKey(TopicModel, on_delete = models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add = True)
def __str__(self):
if len(self.text) < 20:
return self.text
return self.text[:20] + '...'
class Meta:
verbose_name = 'Entry'
verbose_name_plural = 'Entries'
条目与主题的关系,通常是多对一的,因此在创建条目类 EntryModel 时,为其添加了一个外键,关联一个特定的主题。
注意,新加入的模型要想使用的话,一定一定要在 admin.py 中进行注册
# admin.py
from django.contrib import admin
# Register your models here.
from notes.models import TopicModel, EntryModel
admin.site.register(TopicModel)
admin.site.register(EntryModel)
迁移数据库并重启:
$ python manage.py makemigrations notes
Migrations for 'notes':
notes/migrations/0003_entrymodel.py
- Create model EntryModel
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, notes, sessions
Running migrations:
Applying notes.0003_entrymodel... OK
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
September 14, 2022 - 07:56:18
Django version 4.1.1, using settings 'my_note.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
现在重新登录网页端,就可以新增条目并关联主题辣~
添加条目并关联主题:
条目长度大于 20 则自动显示省略号:
至此,一个简单的网页笔记就创建完成了。