Python全栈之路-Django(八)
1 CBV
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test.html$', views.test),
url(r'^login.html$', views.Login.as_view()),
]
app01.views.py
from django.views import View
class Login(View):
"""
get 查找
post 创建
put 更新
delete 删除
"""
# 寻找类里面的功能函数
def dispatch(self, request, *args, **kwargs):
# 类似装饰器功能
print('执行前')
obj = super(Login, self).dispatch(request, *args, **kwargs)
print('执行后')
return obj
def get(self, request):
# return HttpResponse('Login get')
return render(request, 'login.html')
def post(self, request):
print(request.POST.get('user'))
return HttpResponse('Login post')
templates.login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login.html" method="post">
{% csrf_token %}
<input type="text" name="user">
<input type="submit" value="提交">
</form>
</body>
</html>
2 ORM 操作
ForeignKey 正/反向操作以及连表操作
from django.shortcuts import render,HttpResponse
# Create your views here.
# 数据库操作
from app01 import models
def test(request):
# 创建数据
# models.UserType.objects.create(title='普通用户')
# models.UserType.objects.create(title='超级用户')
# models.UserType.objects.create(title='牛逼用户')
# models.UserInfo.objects.create(name='万永振', age=18, ut_id=2)
# models.UserInfo.objects.create(name='李智', age=18, ut_id=2)
# models.UserInfo.objects.create(name='温艳杰', age=18, ut_id=1)
# models.UserInfo.objects.create(name='苏浩智', age=18, ut_id=1)
# models.UserInfo.objects.create(name='杨振威', age=18, ut_id=3)
# models.UserInfo.objects.create(name='韩星宇', age=18, ut_id=3)
# 查找
# 正向操作
result = models.UserInfo.objects.all()
for obj in result:
print(obj.id, obj.name, obj.age, obj.ut_id, obj.ut.title)
result = models.UserInfo.objects.all().first() # 取一行数据
print(obj.id, obj.name, obj.age, obj.ut_id, obj.ut.title) # ut是ForeignKey字段
# 反向操作
# 表名小写_set.all() 查找与之关联的多条数据行
result = models.UserType.objects.all()
for obj in result:
print(obj.id, obj.title, obj.userinfo_set.all()) # obj.userinfo_set.all() QuerySet类型
result = models.UserType.objects.all()
for item in result:
print(item.title, item.userinfo_set.filter(name='万永振'))
# 连表操作
# 0 默认
# QuerySet 里面是对象类型 遍历时可以跨表(会产生多次查询,效率低)
result = models.UserInfo.objects.all()
result = models.UserInfo.objects.filter(id=1)
# 1 .values
result = models.UserInfo.objects.all().values('id', 'name')
# result = models.UserInfo.objects.all().values('id', 'name', 'ut__title') # 获取数据时跨表
# QuerySet 但是里面是字典类型 遍历时不能跨表
for row in result:
print(row) # {'id': 1, 'name': '万永振'} ...
# 2 .values_list
result = models.UserInfo.objects.all().values_list('id', 'name')
# result = models.UserInfo.objects.all().values_list('id', 'name', 'ut__title') # 获取数据时跨表
# QuerySet 但是里面是元组类型 遍历时不能跨表
for row in result:
print(row) # (1, '万永振') ...
# 反向操作
# 1. 小写的表名_set
obj = models.UserType.objects.all().first()
result = obj.userinfo_set.all()
print(result)
# 2. 小写的表名
result = models.UserType.objects.all().values('id', 'title')
print(result)
result = models.UserType.objects.all().values('id', 'title', 'userinfo')
print(result)
result = models.UserType.objects.all().values('id', 'title', 'userinfo__age')
print(result)
return HttpResponse('...')
3 分页
分批获取数据
models.UserInfo.objects.all()[0:10]
models.UserInfo.objects.all()[10:20]
3.1 Django自带分页
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test.html$', views.test),
url(r'^login.html$', views.Login.as_view()),
url(r'^index.html$', views.index),
]
app01.views.py
from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage
from django.shortcuts import render,HttpResponse
def index(request):
"""
分页功能
:param request:
:return:
"""
# 生产测试数据
# for i in range(300):
# name='root' + str(i)
# models.UserInfo.objects.create(name=name, age=18, ut_id=1)
current_page = request.GET.get('page')
user_list = models.UserInfo.objects.all()
paginator = Paginator(user_list, 10)
# per_page: 每页显示条目数量
# count: 数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page: page对象
try:
posts = paginator.page(current_page)
except PageNotAnInteger as e:
# 非数字跳到第一页
posts = paginator.page(1)
except EmptyPage as e:
# 负数跳到第一页
posts = paginator.page(1)
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
# paginator paginator对象
return render(request, 'index.html', {'posts': posts})
templates.index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户列表</h1>
<ul>
{% for user in posts.object_list %}
<li>{{ user.name }} </li>
{% endfor %}
</ul>
<div>
{% if posts.has_previous %}
<a href="/index.html?page={{ posts.previous_page_number }}">上一页</a>
{% endif %}
{% for num in posts.paginator.page_range %}
<a href="/index.html?page={{ num }}">{{ num }}</a>
{% endfor %}
{% if posts.has_next %}
<a href="/index.html?page={{ posts.next_page_number }}">下一页</a>
{% endif %}
</div>
</body>
</html>
3.2 自定义分页
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test.html$', views.test),
url(r'^login.html$', views.Login.as_view()),
url(r'^index.html$', views.index),
url(r'^custom.html$', views.custom),
]
views.py
from utils.pager import PageInfo
from django.shortcuts import render
def custom(request):
all_count = models.UserInfo.objects.all().count()
page_info = PageInfo(request.GET.get('page'), 10, all_count, '/custom.html')
user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]
return render(request, 'custom.html', {'user_list': user_list, 'page_info': page_info})
utils.pager.py
#!/usr/bin/env python
# __Author__: "wanyongzhen"
# Date: 2017/7/3
# 自定义分页
class PageInfo(object):
def __init__(self, current_page, per_page, all_count, base_url, show_page=11):
"""
:param current_page: 当前页的页码
:param per_page: 每页显示的行数
:param all_count: 总行数
:param base_url: 指定url地址
:param show_page: 总共显示多少页码
"""
try:
self.current_page = int(current_page)
except Exception as e:
self.current_page = 1
self.per_page = per_page
self.all_count = all_count
self.base_url = base_url
self.show_page = show_page
a, b = divmod(self.all_count, per_page)
if b:
a = a + 1
self.all_pager = a # 总页数
if self.current_page < 1 or self.current_page > self.all_pager:
self.current_page = 1
def start(self):
return (self.current_page - 1) * self.per_page
def end(self):
return self.current_page * self.per_page
def pager(self):
page_list = []
half = int((self.show_page - 1) / 2)
# 如果数据总页数 < 11
print(self.all_pager, self.show_page)
if self.all_pager < self.show_page:
begin = 1
stop = self.all_pager + 1
# 如果数据总页数 >= 11
else:
# 如果当前页小于等于half 永远显示 1 - 11页
if self.current_page <= half:
begin = 1
stop = self.show_page + 1
# 如果当前页大于half并且小于(最大页-half)正常显示
elif self.current_page > half and self.current_page < (self.all_pager - half):
begin = self.current_page - half
stop = self.current_page + half + 1
# 如果当前页大于等于(最大页-half) 显示最后11页
elif self.current_page >= (self.all_pager - half):
begin = self.all_pager - self.show_page
stop = self.all_pager + 1
# begin = self.current_page - half
# stop = self.current_page + half + 1
if self.current_page <= 1:
prev = "<li><a href='%s?page=%s'>上一页</a></li>" % (self.base_url, self.current_page)
else:
prev = "<li><a href='%s?page=%s'>上一页</a></li>" % (self.base_url, self.current_page - 1)
page_list.append(prev)
for i in range(begin, stop):
if i == self.current_page:
temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i)
else:
temp = "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i)
page_list.append(temp)
if self.current_page >= self.all_pager:
after = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page)
else:
after = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page + 1)
page_list.append(after)
return ''.join(page_list)