学习 Django
1. 初识Django命令
(1). 基本命令
命令 | 作用 |
---|
startproject | 启动Django项目 | startapp | 启动Django应用 | check | 校验项目完整性 | runserver | 运行项目 | shell | Django Shell | test | 执行Django测试用例 |
(2). 数据库相关命令
命令 | 作用 |
---|
makemigrations | 创建模型变更的迁移文件 | migrate | 执行上一个makemigrations 命令创建的迁移文件 | dumpdata | 把数据库数据导出到文件 | loaddata | 把文件数据导入数据库 |
2. 初识Django项目
(1). 创建项目
django-admin startproject 项目名字
文件 | 作用 |
---|
settings.py | Django项目配置文件 | urls.py | Django项目路由文件 | wsgi.py | Django项目作为wsgi应用文件 | manage.py | Django项目管理文件 |
(2). 启动项目
python manage.py runserver
3. 初识Django应用
(1). Django应用
一个Django项目包含一组配置和若干个Django应用
一个Django项目就是一个基于Django的Web应用
一个Django应用就是一个可重用的Python软件包
每个应用可以自己管理模型、视图、模板、路由和静态文件等
应用可以重复包含
(2). 创建应用
python manage.py startapp 应用名称
(3). 应用目录
文件 | 作用 |
---|
views.py | 视图处理 | models.py | 定义应用模型 | admin.py | 定义模块管理 | apps.py | 声明应用 | tests.py | 编写测试用例 | urls.py | (自行创建) 管理应用路由 |
4. Django视图
使用Django视图编写 hello world 函数
1). 在Django应用的views.py文件中创建视图函数
首先要导入模块
from django.http import HttpResponse
def helloWorld (request):
return HttpResponse('hello world')
2). 应用层面的路由配置: 在Django应用的urls.py文件中 配置路由绑定试图函数和url
这是配置应用层面的路由
import 应用名称.views
from django.urls import path
urlpatterns = [
path('hello_world', 应用名称.views.helloWorld),
]
3). 项目层面的路由配置: 在Django项目的urls.py文件中 配置路由绑定试图函数和url
这是配置项目层面的路由
urlpatterns = [
...
path('映射url/', include('应用名称.urls'))
...
]
4). 将应用添加到Django配置文件中
INSTALLED_APPS = [
...
'应用名称.apps.XXXConfig',
]
4. Django模型层
1. 什么是模型层
位于Django视图层和数据库之间, 用于将Python对象和数据库表之间的转换
模型层作用:
- 屏蔽不同数据库之间的差异
- 让开发者更加专注于业务逻辑的开发
- 提供了很多便捷的工具有利于开发
2. 模型层数据库配置
在Django项目的setting.py文件中
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
3. 模型层例子
(1). 模型层定义字段
自增类型
自增类型 | 作用 |
---|
AutoField | 主键自增 | BigAutoField | 更大长度的主键自增 |
二进制和布尔类型
二进制和布尔类型 | 作用 |
---|
BinaryField | 二进制 | BooleanField | 布尔类型 | NullBooleanField | 不能为空的布尔类型 |
整数类型
整数类型 | 作用 | 长度 |
---|
PostitiveSmallIntegerField | 正整数 | 5字节 | SmallIntegerField | 整数 | 6字节 | PostitiveIntegerField | 正整数 | 10字节 | IntegerField | 整数 | 11字节 | BigIntegerField | 整数 | 20字节 |
字符和文本类型
字符和文本类型 | 数据库对应类型 |
---|
CharField | varchar | TextField | longText |
时间类型
时间类型 | 作用 | 数据库类型 |
---|
DateField | 年月日 | | DateTimeField | 年月日时分秒 | | DurationField | Python timedelta | int类型 |
浮点类型
浮点类型 | 作用 |
---|
FloatField | 小数 | DecimalField | 小数 |
其他类型
其他类型 | 作用 |
---|
EmailField | 邮箱 | ImageField | 图片 | FileField | 文件 | FilePathField | 文件路径 | URLField | url路径 | UUIDField | uuid | GenericIPAdressField | ip地址 |
关系类型
关系类型 | 作用 |
---|
OneToOneField | 一对一 | ManyToManyField | 多对多 | ForeignKey | 多对一或一对多 |
(2). 字段参数
所有字段共有参数
参数 | 作用 | 取值 |
---|
db_column | 指定数据库表中对应字段 | str | primary_key | 主键 | boolean | verbose_name | 备注或别名 | str | unique | 字段唯一 | boolean | null | 数据库中字段是否允许空 | boolean | blank | 表单提交时是否允许为空 | boolean | db_index | 设置索引 | boolean | help_text | 表单显示帮助信息 | str | editable | 用户是否可以更改 | boolean |
个别字段参数
拥有字段 | 参数 | 作用 | 取值 |
---|
CharField | max_length | 指定最大长度 | int | 日期类型 | unique_for_date | 日期是否唯一 | boolean | 日期类型 | unique_for_month | 日期月份是否唯一 | boolean | 日期类型 | unique_for_year | 日期年份是否唯一 | boolean | 日期类型 | auto_now | 更新记录的时间 | boolean | 日期类型 | auto_now_add | 增加记录时的时间 | boolean | DecimalField | max_digits | 数字个数 | int | DecimalField | decimal_places | 小数个数 | int |
关系型字段参数
拥有字段 | 参数 | 作用 | 取值 |
---|
OneToOneField | related_name | 外键关联的反向查询 | str | ForeignKey | on_delete | 级联操作 | 指定值 |
models.CASCADED 级联删除
models.PROTECT 需要先删除关联数据, 才可以删除当前数据
models.SET_NULL 关联数据置空 null = True, blank = True
models.SET_DEFAULT 关联字段值为默认值
models.SET_NOTHING 啥也不做
models.SET() 传递一个值或一个函数的返回值
自关联
一个数据库中的字段关联另一个数据库中的某一字段
地址表中, 地址的字段关联地址
from django.db import models
class AddressInfo(models.Model):
address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自关联")
def __str__(self):
return self.address
(3). 设计博客模型层
在Django应用的models.py文件中定义模型
from django.db import models
class Article(models.Model):
articleId = models.AutoField(primary_key=True)
title = models.TextField()
briefContent = models.TextField()
content = models.TextField()
publishDate = models.DateTimeField(auto_now=True)
def __str__(self) :
return self.title
(4). 模型迁移
python manage.py makemigrations
生成数据库要执行的内容到migrations文件夹下
python manage.py migrate
执行migrations文件夹下的文件, 并将过程记录到django_migrations数据表中(该表是django自动生成的)
python manage.py makemigrations
python manage.py migrate
(5). 注册模型到admin
在应用的admin.py文件中配置
from django.contrib import admin
from .models import Article
admin.site.register(Article)
(6). 模型迁出
将数据库转成models
python manage.py inspectdb > models.py
模型类代码会出现在models.py文件中
(7). 模型删除
1). 删除models.py文件中的模型类代码
2). 删除模型类在migrations文件夹下的对应文件
3). 删除django_migrations表中的记录
4). 删除模型类对应的数据表
4. 初识 Django Shell
1. 什么是 Django Shell
Python Shell是用于交互式的Python编程
Django Shell是用于交互式的Django项目环境
2. 为什么使用 Django Shell
- 临时性操作使用Django Shell更加方便
- 小范围Debug更简单,不需要运行整个项目来测试
3. 使用 Django Shell
(1). 进入 Django Shell
python manage.py shell
(2). 使用Django Shell导入数据
新建文章
from testapp1.models import Article
a = Article()
a.title = 'Test Django Shell'
a.brief_content = 'Mzy'
a.content = 'Test new Article'
a.save()
articles = Article.objects.all()
article = articles[0]
5. 初识 Django Admin
(1). 什么是 Django Admin
Django框架的后台管理工具
可以读取定义的模型元数据, 提供强大的管理使用页面
(2). 为什么使用 Django Admin
- 方便添加数据
- 管理页面
(3). 使用 Django Shell
1). 创建管理员用户
python manage.py createsuperuser
2). 登录进入管理系统
访问admin
6. 初识 Django 模板系统
模板系统的表现形式是文本
1. 基本语法
标签 | 作用 |
---|
{{变量}} | 变量标签 | {% for x in list %}, {% endfor %} | for循环标签 | {% if %}, {% else %}, {% endif %} | if-else标签 | {% load static %} | 使用静态文件, 自动查找static目录 | {% csrf_token %} | 跨域 |
2. 使用模板系统
在应用的views.py文件写视图
使用render返回html页面, 默认去应用的templates文件夹里找
def getIndexPage(request):
articles = Article.objects.all()
return render(request, 'index.html', {
'articles': articles
})
在应用的urls.py文件配置路由
urlpatterns = [
path('hello_world', testapp1.views.helloWorld),
path('getArticle', testapp1.views.getArticle),
path('index', testapp1.views.getIndexPage),
path('detail', testapp1.views.getDetailPage),
]
3. 获取url路径参数
urlpatterns = [
path('detail/<int:articleId>', testapp1.views.getDetailPage)
]
def getDetailPage(request, articleId):
articles = Article.objects.all()
article = None
for i in articles:
if i.articleId == articleId:
article = i
break
return render(request, 'detail.html', {
'article': article
})
6. 初识 Django ORM
(1). ORM
Object Relational Mapping
(2). 配置数据库
setting.py文件中配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'PythonTest',
'USER': 'root',
'PASSWORD': 'Lyj20010402',
'HOST': 'bj-cynosdbmysql-grp-f9k1u8e0.sql.tencentcdb.com',
'PORT': '25483'
}
}
安装mysqlclient
pip install mysqlclient
安装PyMySQL
pip install PyMySQL
(3). 元数据
from django.db import models
class AddressInfo(models.Model):
address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自关联")
def __str__(self):
return self.address
class Meta:
db_table = 'address'
ordering = [
'pid'
]
verbose_name = '地址信息'
verbose_name_plural = verbose_name
abstract = False
permissions = (
('权限', '说明'),
)
managed = True
unique_together = (
(), ()
)
app_label = 'testapp1'
db_tablespace = ''
(4). 实战建表
讲师信息表 课程信息表 学生信息表 助教信息表
助教和讲师是一对一
课程和讲师是多对一
学生信息和课程是多对多
讲师和课程 讲师是父表, 课程是子表
课程和学生 课程是父表, 学生是子表
讲师和助教 讲师是父表, 助教是子表
1). 讲师表
from django.db import models
class Teacher(models.Model):
nickname = models.CharField(
max_length = 30,
primary_key = True,
db_index = True,
verbose_name = "昵称"
)
introduction = models.TextField(
default = "这位同学很懒, 木有签名~",
verbose_name = "个性签名"
)
fans = models.PositiveIntegerField(
default = 0,
verbose_name = "粉丝数"
)
createTime = models.DateTimeField(
auto_now_add = True,
verbose_name = "创建时间"
)
updateTime = models.DateTimeField(
auto_now = True,
verbose_name = "修改时间"
)
class Meta:
verbose_name = "讲师信息表"
verbose_name_plural = verbose_name
2). 课程表
from django.db import models
class Course(models.Model):
"""课程信息表"""
title = models.CharField(
max_length = 100,
primary_key = True,
db_index = True,
verbose_name = "课程名"
)
type = models.CharField(
choices = (
(1, "实战课"), (2, "免费课"), (3, "其他")
),
max_length = 1,
default = 0,
verbose_name = "课程类型"
)
price = models.PositiveIntegerField(
verbose_name = "价格"
)
volume = models.PositiveBigIntegerField(
verbose_name = "销量"
)
createTime = models.DateTimeField(
auto_now_add = True,
verbose_name = "上线时间"
)
updateTime = models.DateTimeField(
auto_now = True,
verbose_name = "更新时间"
)
teacher = models.ForeignKey(
Teacher,
on_delete = models.CASCADE,
null = True,
blank = True,
verbose_name = "课程讲师"
)
class Meta:
verbose_name = "课程信息表"
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.get_type_display()}-{self.title}"
get_XXX_display() 函数获取字段
例如, 如果如下类型字段存储的是1, 使用该函数后, 获得1所对应的值, 这里字段使用choice是数据库枚举类型
type = models.CharField(
choices = (
(1, "实战课"), (2, "免费课"), (3, "其他")
),
max_length = 1,
default = 0,
verbose_name = "课程类型"
)
F运算符即format函数简化版, 3.6版本新加入的
原版
>>> a = "{}-{}"
>>> a.format("1", "2")
'1-2'
简化版
>>> a = 1
>>> b = 2
>>> c = f"{a}-{b}"
print(c)
1-2
f"{self.get_type_display()}-{self.title}"
相当于
"{}-{}".format(self.get_type_display(), self.title)
3). 学生信息表
from django.db import models
class Student(models.Model):
"""学生信息表"""
nickname = models.CharField(
max_length = 30,
primary_key = True,
db_index = True,
verbose_name = "昵称"
)
age = models.PositiveSmallIntegerField(
verbose_name = "年龄"
)
gender = models.CharField(
choices = (
(1, "男"), (2, "女"), (0, "保密")
),
max_length = 1,
default = 0,
verbose_name = "性别"
)
fans = models.PositiveIntegerField(
default = 0,
verbose_name = "学习时常"
)
createTime = models.DateTimeField(
auto_now_add = True,
verbose_name = "创建时间"
)
updateTime = models.DateTimeField(
auto_now = True,
verbose_name = "修改时间"
)
course = models.ManyToManyField(
Course,
verbose_name = "课程"
)
class Meta:
verbose_name = "学生信息表"
verbose_name_plural = verbose_name
def __str__(self):
return self.nickname
4). 助教信息表
from django.db import models
class TeacherAssistant(models.Model):
"""助教信息表"""
nickname = models.CharField(
max_length = 30,
primary_key = True,
db_index = True,
verbose_name = "昵称"
)
hobby = models.CharField(
max_length = 100,
null = True,
blank = True,
verbose_name = "爱好"
)
createTime = models.DateTimeField(
auto_now_add = True,
verbose_name = "创建时间"
)
updateTime = models.DateTimeField(
auto_now = True,
verbose_name = "修改时间"
)
teacher = models.OneToOneField(
Teacher,
on_delete = models.SET_NULL,
null = True,
blank = True,
verbose_name = "讲师"
)
class Meta:
verbose_name = "助教信息表"
verbose_name_plural = verbose_name
def __str__(self):
return self.nickname
外键字段写到子表
(5). Models API
使用objects模型类对象管理器进行查询
1). 查询全部数据
使用all() 函数, 返回结果为QuerySet
模型类名.objects.all()
teachers = Teacher.objects.all()
2). 根据指定字段的值查询
使用get() 函数, 返回结果为该类
模型类名.objects.get()
teachers = Teacher.objects.get(nickname = '惠')
teachers = Teacher.objects.get(fans = 54, nickname = '惠')
函数的参数: 字段名 = 值 可以指定多个字段的值
3). 条件查询
使用filter() 函数, 返回结果为QuerySet
模型类名.objects.filter()
函数参数(整数类型) | 解释 | 备注 |
---|
字段名__gte | 大于等于 | | 字段名__gt | 大于 | | 字段名__in | 在…中 | 取值为一个列表、元组或集合 | 字段名__lt | 小于 | | 字段名__lte | 小于等于 | | 字段名__exact | 等于 | | 字段名__isnull | 是不是空 | | 字段名__range | 在…中 | 取值为一个列表、元组或集合 (起始值, 终止值) |
函数参数(字符串类型) | 解释 | 备注 |
---|
字段名__regex | 是否匹配正则表达式 | | 字段名__iregex | 是否匹配正则表达式(不区分大小写) | | 字段名__in | 在…中 | 取值为一个列表、元组或集合 | 字段名__contains | 包含 | | 字段名__icontains | 包含(不区分大小写) | | 字段名__iexact | 等于(不区分大小写) | | 字段名__exact | 等于 | | 字段名__isnull | 是不是空 | | 字段名__startwith | 以…开头 | | 字段名__istartwith | 以…开头(不区分大小写) | | 字段名__endwith | 以…结尾 | | 字段名__iendtwith | 以…结尾(不区分大小写) | |
teachers = Teacher.objects.filter(fans__gte = 20)
4). 查看查询的sql
print(Teacher.objects.filter(fans__gte = 20).query)
5). API
函数 | 解释 | 备注 |
---|
exclude() | 排除满足条件的对象 | | annotate() | 使用聚合函数 | | order_by() | 对查询集进行排序 | | reverse() | 反向排序 | | distinct() | 对查询集去重 | | values() | 返回包含对象具体值的字典的QuerySet | | values_list() | 与values()类似,只是返回的是元组 | | dates() | 根据日期获取查询集 | | datetimes() | 根据时间获取查询集 | | none() | 创建空的查询集 | | union() | 并集 | | intersection() | 交集 | | difference() | 差集 | | select_related() | 附带查询关联对象 | | prefetch_related() | 预先查询 | | extra() | 附加SQL查询 | | defer() | 不加载指定字段 | | only() | 只加载指定的字段 | | using() | 选择数据库 | | select_for_update() | 锁住选择的对象,直到事务结束。 | | raw() | 接收一个原始的SQL查询 | |
可以使用多个参数
7. Django 请求和响应
(1). 请求
request 是一个对象,封装了用户发送过来的所有请求相关数据
请求属性 | 解释 |
---|
request.method | 请求方式 | request.GET | 获得queryString, 类型是: django.http.request.QueryDict | request.POST | 获得请求体, 类型是: django.http.request.QueryDict |
1). 获取请求方法
def learnRequest(request):
method = request.method
print(method)
return HttpResponse('hello world')
2). 获取GET请求的QueryString
发送请求
xxx/xxx?a=123
def learnRequest(request):
queryString = request.GET
print(queryString.get('a'))
return HttpResponse('hello world')
没有键则返回 None
3). 获取POST请求体
def learnRequest(request):
body = request.POST
print(body)
return HttpResponse('123')
(2). 响应
使用HttpResponse 返回字符串
def learnResponse(request):
return HttpResponse('123')
使用render()函数 , 读取html内容, 渲染(替换)为字符串, 返回给浏览器
def learnResponse(request):
return render(request, 'index.html', {
'variable': 'value'
})
使用redirect() 函数重定向
def learnResponse(request):
return redirect('https://www.baidu.com')
|