django运行图解及说明
一.创建项目:
django-admin startproject 项目名
二.创建应用:
python manage.py startapp 应用名
三.django的执行过程:
看图片
四.URL配置:
url(r'^', include('cart.urls'))::项目同名下的
url(r'^index/$', views.index):应用下的
1.未命名参数(位置参数): 按定义的顺序传递,匹配成功就传入到视图函数
# 在项目下的 urls.py 文件中配置
url(r'^news/(\d+)/(\d+)$', users.views.news),
# 在 users/views.py 中定义
def news(request, a, b):
return HttpResponse("显示新闻:%s %s" % (a,b)
2.命名参数(关键字参数): 按定义的组名传递
# 在项目下的 urls.py 文件中配置
url(r'^news/(?P<category>\d+)/(?P<page>\d+)$', users.views.news),
# 在 users/views.py 中定义
def news(request, category, page):
return HttpResponse("显示新闻:%s %s" % (category, page)
五.请求与响应:
1.request对象(最后用.get()获取数据):
(1).user:
已登录:AbstractUser对象;未登录:AnonymousUser对象;request.user.is_authenticated()为true表示已登录.
(2).GET:
类似字典的QueryDict对象,包含url中所有的查询字符串参数.
(3).POST:
类似字典的QueryDict对象(一个键可以保存多个值),包含POST请求的所有键值对参数.
(4).FILES:
类似于字典的对象,包含所有上传的文件.
(5).body:
获取原始的请求体数据,获取到的数据为bytes类型,非标单数据JSON、XML.
(6).META:
python的字典类型,封装了请求头headers中的数据
- REMOTE_ADDR:客户端的IP地址
注意:对于用户添加到请求头中的键值,Django会给键加上前缀HTTP_再转换成大写,再把键值保存到request.META中
(7).COOKIES:
一个标准的python字典,包含所有的cookies,键和值都是字符串.
(8).session:
可读可写的类似字典的对象: django.contrib.sessions.backends.db.SessionStore。
Django 提供了 session 模块,默认就会开启用来保存 session 数据
2.QueryDict对象:
(1).get()方法:
- 根据键获取值
- 如果一个键有多个值,将获取最后一个值
- 如果键不存在则返回None值,可以设置返回自定义的默认值
dict.get('键',默认值)
(2).getlist()方法:
- 根据键获取多个值,值一列表返回
- 如果键不存在则返回空列表
dict.getlist('键', 默认值)
3.response:HttpResponse(content=响应体, content_type=响应体数据MIME类型, status=状态码)
- 视图必须返回一个 HttpResponse 对象(或其子类对象),不能像Flask一样直接返回字符串
- 可以将要返回的字符串数据传给 HttpResponse 对象再返回
- HttpRequest对象由Django创建,HttpResponse对象由开发人员创建
(1).响应头设置:
response = HttpResponse('响应内容')
response['hello'] = 'world'
(2).JsonResponse
- 传入字典:
return JsonResponse({'name': 'Jack', 'age': 20})
- 传入非字典:
return JsonResponse([{'name': 'Jack'},{'name': 'Lucy'}], safe=False)
(3).redirect重定向:
# 重定向到首页
return redirect('/index')
4.Cookie:
(1).设置Cookie:
response.set_cookie('键','值',max_age)
(2).读取Cookie
request.COOKIES.get('键')
5.Session:
i:session数据默认保存在django项目的一张数据库表中(表名为:django_session)
ii:在保存session数据库前,需要先生成django项目默认的数据库表;
iii:如何生成: 打开终端,并进入到项目根目录下,再执行以下2个命令生成数据库表:
python manage.py makemigrations
python manage.py migrate
(1).生成session数据:
request.session['键'] = 值
(2).读取sessiion数据:
request.session.get('键','默认值')
(3).删除命令:
# 删除一个sessoin键值对(注意:键不存在会报错 `KeyError`)
del request.session['键']
(4).设置session数据有效时间;如果不设置,默认过期时间为两周:
request.session.set_expiry(value)
- 如果value是一个整数,则 session数据 将在value秒没有活动后过期
- 如果value为0,则 session数据 将在用户 关闭浏览器时过期
- 如果value为None,则 session数据 将在 2周后过期
六.类视图:
1.继承Django提供的View类,请求方式对应类方法
2.注册路由:url(r'^post2$', views.PostView.as_view())
3.给类视图添加装饰器:check_ip
(1) 给类视图的特定的方法添加装饰器:
class PostView(View):
def get(self, request):
return render(request, 'post2.html')
@method_decorator(check_ip)
def post(self, request):
return HttpResponse('处理发帖操作')
(2)给类视图的所有方法应用装饰器:
class PostView(View):
@method_decorator(check_ip)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request):
return render(request, 'post2.html')
七.中间件:
1.定义中间件类: 通过继承Django的MiddlewareMixin扩展类实现,可以重写以下两个核心方法:
方法名 作用 返回值
process_request(self, request) 在视图执行之前调用 返回 `None`: 会执行视图;返回 `HttpResponse`: 不 会再执行视图
process_response(self, request, response) 在视图执行完之后调用 必须返回HttpResponse对象
2.在settings.py 文件中添加注册中间件
八.模板:
模板渲染:
from django.template import loader
def index(request):
context = {'name': 'django' }
# 获取模板对象
template = loader.get_template('index.html')
# 渲染得到字符串
html_str = template.render(context)
# 响应请求
return HttpResponse(html_str)
九.数据库(继承:models.Model):
1.生成迁移文件:
python manage.py makemigrations
2.生成数据表:
python manage.py migrate
3.在与项目同名包下的__init__()文件中,初始化mysql驱动:
import pymysql
pymysql.install_as_MySQLdb()
4.关联属性on_delete选项的取值:
(1)models.CASCADE 此为默认值,级联删除,会删除关联数据:
department = models.ForeignKey('Department',on_delete=models.CASCADE)
(2)models.PROTECT 只要存在关联数据就不能删除:
department = models.ForeignKey('Department', on_delete=models.PROTECT)
(3)models.SET_NULL 删除数据后关联字段设置为NULL,仅在该字段允许为null时可用(null=True):
department = models.ForeignKey('Department',on_delete=models.SET_NULL)
5.代码参考:
class Employee(models.Model):
"""员工类"""
choices_gender = (
(0, '男'),
(1, '女'),
)
name = models.CharField(max_length=20)
age = models.IntegerField()
gender = models.IntegerField(default=0, choices=choices_gender)
# 工资:浮点类型(必须要指定两个选项) 999999.99
salary = models.DecimalField(max_digits=8, decimal_places=2)
# 备注信息: 可以为空
comment = models.CharField(max_length=300, null=True, blank=True)
# 员工入职时间
hire_date = models.DateField(auto_now_add=True)
# 一对多的外键:员工所属部门 department_id
department = models.ForeignKey('Department')
def __str__(self):
return self.name
class Meta:
# 指定表名
db_table = 'employee'
6.增删改(filter查询出来才能后接删除更新操作):
(1).增:
1.模型类.objects.create(属性1=值1,属性2=值2, ...):
Department.objects.create(
name='后勤部',
create_date='2017-1-1'
)
2.模型类对象.save():
d = Department()
d.name = '人事部'
d.create_date = '2017-1-1'
d.save()
(2).删:
1.模型类对象.delete():
d = Department.objects.get(id=1)
d.delete()
2.模型类.filter(条件).delete():
Department.objects.filter(id=1).delete()
(3).改:
1.模型类对象.save():
d = Department.objects.get(id=1)
d.name = '人事部'
d.save()
2.模型类.filter(条件).update(属性1=值1,属性2=值2, ...):
Department.objects.filter(id=1).update(name='人事部')
7.查询:
(1)条件查询(filter):
1.模糊查询: contains / endswith / startswith:
查询名字包含'马'的员工:
Employee.object.filter(name__contains='马')
2.空查询: isnull
查询备注信息不为空的员工:
Employee.objects.filter(comment__isnull=False)
3.范围查询: in
查询id编号为1或3或5的员工:
Employee.objects.filter(id__in=[1,3,5])
4.比较查询: gt(greater than)、lt(less than)、gte、lte
查询age大于等于30的员工:
Employee.objects.filter(age__gte=30)
5.日期查询: year、month、day、week_day、hour、minute、second
查询2015年入职的员工:
Employee.objects.filter(hire_date__year=2015)
查询2014年1月1日后入职的员工
Employee.objects.filter(hire_date__gte='2014-1-1')
(2)exclude方法:
查询id不为3的员工
Employee.objects.exclude(id=3)
(3)F对象:两个属性之间的比较
查询年龄大于id的员工信息:
Employee.objects.filter(age__gt=F('id'))
(4).Q对象(& | ~)
查询id大于3且年龄大于30的员工信息:
Employee.objects.filter(id__gt=3, age__gt=30)
查询id大于3或者年龄大于30的员工信息:
Employee.objects.filter(Q(id__gt=3)|Q(age__gt=30))
查询id不等于3员工信息:
Employee.objects.filter(~Q(id=3))
(5).排序order_by:
升序: 模型类.objects.order_by('属性名')
降序: 模型类.objects.order_by('-属性名')
把id大于8的员工信息, 按年龄从大到小排序显示:
Employee.objects.filter(id__gt=8).order_by('-age')
(6).aggregate 方法:
用法: 模型类.objects.aggregate(聚合类('属性名'))
常用聚合类有:Sum, Count, Max, Min, Avg等
查询所有员工的平均工资:
Employee.objects.aggregate(Avg('salary'))
(7).关联查询
有关联属性(多对一查询): 模型类对象.关联属性
没有关联属性(一对多查询):模型类对象.关联模型
查询 “研发部” 的所有员工:
d = Department.objects.get(name='研发部')
d.employee_set.all()
查询 “赵小二” 所属的部门信息:
e = Employee.objects.get(name='赵小二')
e.department()
8.查询集 QuerySet:
1.概念:当调用模型管理器的 all, filter, exclude, order_by等方法时,返回的是一个 QuerySet 对象,表示从数据库查询到的数据集合;
2. 支持下标和切片操作:
query_set[0]:取出查询集中的第一条数据,不存在会抛IndexError异常
query_set[0:2]:切片操作得到另一个新的QuerySet
注意:下标不能为负数
3.查询集两大特性
(1). 惰性查询
创建查询集时不会访问数据库,操作查询集中的数据时才会访问;
(2).缓存功能
当遍历(迭代)访问查询集 所有数据,会缓存查询集所有数据,当再次操作该查询集中的数据时,将会使用缓存;但如果只是访问查询集 部分数据(下标或切片)不会缓存
# 创建查询集
query_set = Department.objects.all()
# 会查询数据库
[dep.name for dep in query_set]
# 使用缓存,不再查数据库
[dep.name for dep in query_set]
10.admin站点
(1).注册模型类:在应用下的admin.py中注册模型类,注册后才会在管理后台显示:
admin.site.register(Department)
(2).自定义列表页展示
1. 定义显示哪些字段:
# users/admin.py:
class EmployeeAdmin(admin.ModelAdmin):
# 指定要显示的属性
list_display = ["id", "name", "age", "gender", "comment", "department"]
# 参数2: 注册Admin类
admin.site.register(Employee, EmployeeAdmin)
2. 修改表头显示的名字:
在定义模型类的类属性时,使用 verbose_name 选项来指定在后台的字段显示
3. 定义每页显示多少条:
users/admin.py:
class EmployeeAdmin(admin.ModelAdmin):
...
list_per_page = 5 # 每页显示5条,默认为100
4.显示或隐藏操作栏:
# users/admin.py
class DepartmentAdmin(admin.ModelAdmin):
...
# 显示顶部操作栏
actions_on_top = True
# 显示底部操作栏
actions_on_bottom = True
5. 显示过滤器栏:
# users/admin.py
class EmployeeAdmin(admin.ModelAdmin):
...
# 显示过滤栏: 按性别和部门过滤
list_filter = ['gender', 'department']
6.显示搜索栏
# users/models.py
class DepartmentAdmin(admin.ModelAdmin):
...
# 搜索部门名称
search_fields = ['name']