Django模型和后台的简单介绍
author: Once Day date:2022年2月13日
本文档在于总结相关内容,零散的知识难以记忆学习。
本文档基于windows平台。
1.数据库配置
在 初识Django 文章里已经介绍过了,Django基于MTV设计模式,第一个M(model)便是模型,它负责提供逻辑和数据的接口,所谓数据便是数据库。
Django默认使用SQLite3数据库,因为Python原生支持SQLite3数据库,所以无须安装任何程序,就可以直接使用它。在学习的时候,使用SQLite3可省略很多麻烦。
mysite/settings.py配置文件里可看到详情:
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
上面是默认的数据库配置,其中:
- ENGINE(引擎):可以是
django.db.backends.sqlite3
、django.db.backends.postgresql
、django.db.backends.mysql
、django.db.backends.oracle
,当然其它的也行。 - NAME(数据库名称):数据库的名称。如果你使用的是默认的SQLite3,那么数据库将作为一个文件将存放在你的本地机器内,此时的NAME应该是这个文件的完整绝对路径包括文件名,默认情况下该文件储存在你的项目根目录下。
使用其他数据库时将有额外的信息需要填写,这里只考虑使用SQLite3。
2.创建模型
Django通过自定义Python类的形式来定义具体的模型,每个模型的物理存在方式就是一个Python的类Class,每个模型代表数据库中的一张表,每个类的实例代表数据表中的一行数据,类中的每个变量代表数据表中的一列字段。Django通过模型,将Python代码和数据库操作结合起来,实现对SQL查询语言的封装。可以不会SQL语言,同样能通过Python的代码进行数据库的操作,这就是所谓的ORM。
下面创建账户和个人信息两个模型:
#login/models.py
from django.db import models
# Create your models here.
class user_information(models.Model):
user_name = models.CharField(max_length=20)
user_birthday = models.DateTimeField("birthday")
user_money = models.IntegerField(default=1000)#默认1000积分
class account(models.Model):
user = models.ForeignKey(user_information,on_delete=models.CASCADE)
account_name = models.CharField(max_length=30)#账户名最大字符长度30
password =models.CharField(max_length=60)#密码长度最大60
可以在每个Field中使用一个可选的第一位置参数用于提供一个人类可读的字段名,让你的模型更友好,更易读,并且将被作为文档的一部分来增强代码的可读性。比如例子中的birthday
定义了对人类友好的名字。
这里使用ForeignKey
定义了一个外键关系。它告诉Django,每一个Choice关联到一个对应的Question(注意要将外键写在‘多数’的一方)。Django支持通用的数据关系:一对一,多对一和多对多。
模型代码具体编写可参考:
- django Part 2:模型与后台 - 刘江的django教程 (liujiangblog.com)
- Django 模型_w3cschool
- Models_w3cschool
3.启用模型
依靠上面的模型Django可以该app对应的数据库表结构并创建基于Python的数据库访问API。
首先需要注册login这个APP,
#mysite/setting.py
# Application definition
INSTALLED_APPS = [
'login',#这是一种简写,大多数情况下够用,实际上指到login/apps.py里的LoginConfig
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
注册之后,需要记录对模型文件的更改,运行以下命令:
PS E:\django\mysite> python manage.py makemigrations login
Migrations for 'login':
login\migrations\0001_initial.py
- Create model user_information
- Create model account
通过运行makemigrations
命令,Django 会检测对模型文件的修改,并且把这些改动保存为一个“迁移(migration)
”。
migrations
是Django保存模型修改记录的文件,这些文件保存在磁盘上。在例子中,它就是polls/migrations/0001_initial.py
,可以打开它看看,里面保存的都是人类可读并且可编辑的内容,方便随时手动修改。
可以使用sqimigrate命令展示SQL语句,
PS E:\django\mysite> python manage.py sqlmigrate login 0001
BEGIN;
--
-- Create model user_information
--
CREATE TABLE "login_user_information" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "user_name" varchar(20) NOT NULL, "user_birthday" datetime NOT NULL, "user_money" integer NOT NULL);
--
-- Create model account
--
CREATE TABLE "login_account" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "account_name" varchar(30) NOT NULL, "password" varchar(60) NOT NULL, "user_id" bigint NOT NULL REFERENCES "login_user_information" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "login_account_user_id_b635b0f5" ON "login_account" ("user_id");
COMMIT;
注意这些指令的输出和使用的数据库有关!
也可以运行check命令,它将检查项目中的错误,并不实际进行迁移或者链接数据库的操作。
PS E:\django\mysite> python manage.py check
System check identified no issues (0 silenced).
接下来实际迁移,
PS E:\django\mysite> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, login, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying login.0001_initial... OK
Applying sessions.0001_initial... OK
migrate命令对所有还未实施的迁移记录进行操作,本质上就是将你对模型的修改体现到数据库中具体的表中。Django通过一张叫做 django_migrations 的表,记录并跟踪已经实施的migrate动作,通过对比获得哪些迁移尚未提交。
记住修改模型时的操作分三步:
- 在models.py中修改模型;
- 运行
python manage.py makemigrations
为改动创建迁移记录文件; - 运行
python manage.py migrate
,将操作同步到数据库。
这些步骤在版本控制中比较有效!
4.尝试ORM
Django模型层自带ORM系统,会自动为每个模型创建数据库访问的API,直接拿来用就可以,非常简单、方便、易学。
下面,让我们进入Python交互环境,尝试使用Django提供的数据库访问API。相比较直接输入“python”命令的方式进入Python环境,调用manage.py
参数能将DJANGO_SETTINGS_MODULE
环境变量导入,它将自动按照mysite/settings.py
中的设置,配置好你的python shell环境,这样,你就可以导入和调用任何你项目内的模块了。
PS E:\django\mysite> python manage.py shell
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
然后进行一些基本操作,注意脚本命令和写代码是一样的使用方式:
>>> from login.models import user_information,account # 导入我们写的模型类
#查询所有的用户信息
>>> user_information.objects.all()
<QuerySet []>
>>> from django.utils import timezone
#获取时间
>>> timezone.now()
datetime.datetime(2022, 2, 13, 4, 20, 57, 797311, tzinfo=datetime.timezone.utc)
#转化为本地时间
>>> timezone.localtime(timezone.now())
datetime.datetime(2022, 2, 13, 12, 23, 28, 577106, tzinfo=zoneinfo.ZoneInfo(key='Asia/Shanghai'))
#创建一个用户对象
>>> u1= user_information(user_name="once day",user_birthday=timezone.now(),user_money=100000)
#显示保存到数据库
>>> u1.save()
# 默认情况,你会自动获得一个自增的名为id的主键
>>> u1.id
1
# 通过python的属性调用方式,访问模型字段的值
>>> u1.user_name
'once day'
>>> u1.user_money
100000
# 通过修改属性来修改字段的值,然后显式的调用save方法进行保存。
>>> u1.user_money=99999
>>> u1.user_money
99999
>>> u1.save()
#查询对象
>>> u1
<user_information: user_information object (1)>
上面的<Question: Question object>
是一个不可读的内容展示,你无法从中获得任何直观的信息,为此我们需要一点小技巧,让Django在打印对象时显示一些我们指定的信息。
#login/models.py
from django.db import models
# Create your models here.
class user_information(models.Model):
user_name = models.CharField(max_length=20)
user_birthday = models.DateTimeField("birthday")
user_money = models.IntegerField(default=1000)#默认1000积分
def __str__(self) -> str:
return self.user_name+':'+str(self.user_money)
def add_money(self,money):#加钱
self.user_money+=money
return self.user_money
class account(models.Model):
user = models.ForeignKey(user_information,on_delete=models.CASCADE)
account_name = models.CharField(max_length=30)#账户名最大字符长度30
password =models.CharField(max_length=60)#密码长度最大60
def __str__(self) -> str:
return self.account_name
上面重载了一个内部函数__str__
,可告诉python解释器打印什么内容。并且新增一个加钱函数。
重启命令行!然后进行下列操作
>>> from login.models import user_information,account # 导入我们写的模型类
#获取之前创建的对象
>>> u1=user_information.objects.get(id=1)
#这下可以打印关键信息
>>> u1
<user_information: once day:99999>
#查询所有的对象
>>> user_information.objects.all()
<QuerySet [<user_information: once day:99999>]>
# Django提供了大量的关键字参数查询API
>>> user_information.objects.filter(id=1)
<QuerySet [<user_information: once day:99999>]>
>>> user_information.objects.filter(user_name="once day")
<QuerySet [<user_information: once day:99999>]>
#使用自定义方法
>>> u1.add_money(1000000)
1099999
>>> u1
<user_information: once day:1099999>
# 显示所有与q对象有关系的choice集合,目前是空的,还没有任何关联对象。
>>> u1.account_set.all()
<QuerySet []>
#创建两个账户
>>> u1.account_set.create(account_name="onceday",password="1234566")
<account: onceday>
>>> u1.account_set.create(account_name="mark",password="123456")
<account: mark>
#再次查询
>>> u1.account_set.all()
<QuerySet [<account: onceday>, <account: mark>]>
#获取第二个账户对象
>>> a1=u1.account_set.get(id=2)
>>> a1.user
<user_information: once day:1099999>
#删除该对象
>>> a1.delete()
(1, {'login.account': 1})
#再次查询,删除成功
>>> u1.account_set.all()
<QuerySet [<account: onceday>]>
这只是模型的基础操作中一部分,可以尝试增强印象!
5.admin后台管理
Django最大的优点之一,就是体贴的为你提供了一个基于项目model创建的一个后台管理站点admin。这个界面只给站点管理员使用,并不对大众开放。
首先创建管理员用户,
PS E:\django\mysite> python manage.py createsuperuser
Username (leave blank to use '54041'): onceday
Email address: 54041551@qq.com
Password:
Password (again):
Superuser created successfully.
然后启动服务器,python manage.py runserver
,浏览器输入http://127.0.0.1:8000/admin/,出现登入界面,输入用户和密码登入。
可以将管理后台的url给换掉,在urls.py配置这里修改即可!
目前站点里面只能看到django.contrib.auth
模块提供的身份认证框架内的模型,Groups和Users。
在admin中注册login应用后,就可以在站点中进行管理!
#login/admin.py
from django.contrib import admin
# Register your models here.
from login.models import user_information
#导入模块并注册
admin.site.register(user_information)
重新运行服务器!并且访问管理站点!
这里需要注意的是:
- 页面中的表单是由user_information模型自动生成的。
- 不同的模型字段类型(DateTimeField, CharField)会表现为不同的
HTML input
框类型。 - 每一个
DateTimeField
都会自动生成一个可点击链接。日期是Today,并有一个日历弹出框;时间是Now,并有一个通用的时间输入列表框。
在页面的底部,则是一些可选项按钮:
delete
:弹出一个删除确认页面save and add another
:保存当前修改,并加载一个新的空白的当前类型对象的表单。save and continue editing
:保存当前修改,并重新加载该对象的编辑页面。save
:保存修改,返回当前对象类型的列表页面。
点击页面右上角的History
,可以看到对当前对象的所有修改操作记录,包括修改时间和操作人员。
如果时间存在问题,是没有正确的配置TIME_ZONE
,在国内,通常是8个小时的时间差别。需要在
mysite/setting.py里修改以下代码:
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
#改下面这一行
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
具体参考文档:
- django Part 2:模型与后台 - 刘江的django教程 (liujiangblog.com)
- Admin_Django Girls 学习指南_w3cschool