学习 Python Django
学习 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',
}
}
修改成mysql数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '数据库名称',
'USER': '用户名',
'PASSWORD': '密码',
'HOST': '',
'PORT': '端口号'
}
}
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="自关联")
# pid = models.ForeignKey('AddressInfo', 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):
# 文章Id
articleId = models.AutoField(primary_key=True)
# 文章标题
title = models.TextField()
# 文章摘要
briefContent = models.TextField()
# 文章内容
content = models.TextField()
# 文章发布日期
publishDate = models.DateTimeField(auto_now=True)
# admin中显示
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': 'xxx',
'HOST': 'xxx',
'PORT': 'xxx'
}
}
安装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="自关联")
# pid = models.ForeignKey('AddressInfo', 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 = (
('权限', '说明'),
)
# 是否按照Django管理模式管理该表
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
# 获取a键的值
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')
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122793.html