woxio770 发表于 2018-8-10 12:59:39

Python Day18 Django 04

原创
批量导入数据
  在urls.py中创建一个url
  

url(r'^books/$', views.books)  

  在models中创建数据表
  

class Book(models.Model):  title = models.CharField(max_length=32)
  price = models.DecimalField(max_digits=8, decimal_places=2)
  

  在视图中,方法1:
  

from django.shortcuts import render, HttpResponse  

  
# Create your views here.
  
from app01.models import Book
  

  
def books(request):
  book_list = []
  for i in range(100):
  book_obj = Book(title="Book_%s" %i, price=i*i)
  book_list.append(book_obj)
  

  #会将上面的实例化对象一次插入到表中
  Book.objects.bulk_create(book_list)
  

  return HttpResponse("OK")
  

  在视图中,方法2:
  

#批量创建数据  
objs =
  

  
#在数据库中批量创建,10次一提交
  
models.Book.objects.bulk_create(objs, 10)
  

  访问:
  http://127.0.0.1:8000/books/

分页器的使用
  print("count:", paginator.count)# 数据总数
  print("num_pages", paginator.num_pages)# 总页数
  print("page_range", paginator.page_range)# 页码的列表 返回一个range
  page = paginator.page(2) #第2页的page对象
  print(page.object_list) #第2页的所有数据
  结果:
  

<QuerySet[ < Book:>  

  for i in page:#遍历第1页的所有数据对象
  print(i)
  

结果:  
title_12
  
title_13
  
title_14
  
title_15
  

  print(page.has_next())# 是否有下一页
  print(page.next_page_number())# 下一页的页码
  print(page.has_previous())# 是否有上一页
  print(page.previous_page_number())# 上一页的页码
  抛错
  page=paginator.page(12)   # error:EmptyPage
  page=paginator.page(&quot;z&quot;)   # error:PageNotAnInteger

views
  

from django.shortcuts import render, HttpResponse  

  
from .models import Book
  
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
  
def index(request):
  # 分页器的使用
  try:
  book_list = Book.objects.all()
  

  paginator = Paginator(book_list, 12)# 获得一个总的分页器对象
  

  # 从url获取page值,如果没有获取就默认1
  c_page = request.GET.get("page", 1)
  # 转换为int类型,不然template识别不了
  currentPage = int(c_page) # 转换为int类型,不然template识别不了
  # 获取page对象
  page = paginator.page(c_page)
  

  except EmptyPage:
  page = paginator.page(1)
  

  return render(request, "index.html", locals())
  

index.html
  

<!DOCTYPE html>  
<html lang="en">
  
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>分页器</title>

  <link>  
</head>
  
<body>
  

  
<ul>
  {% for book in page.object_list %}
  <p>{{ book.title }}:{{ book.price }}</p>
  {% endfor %}
  
</ul>
  

  
<nav aria-label="Page navigation">
  <ul>
  {% if page.has_previous %}
  <li><a href="?page={{ c_page|add:-1 }}" aria-label="Previous">上一页</a></li>
  {% else %}
  <li><a href="?page={{ c_page|add:-1 }}" aria-label="Previous">上一页</a></li>
  {% endif %}
  

  {% for num in paginator.page_range %}
  {% if currentPage == num %}
  <li><a href="?page={{ num }}">{{ num }}</a></li>
  {% else %}
  <li><a href="?page={{ num }}">{{ num }}</a></li>
  {% endif %}
  {% endfor %}
  

  {% if page.has_next %}
  <li><a href="?page={{ c_page|add:+1 }}" aria-label="Next">下一页</a></li>
  {% else %}
  <li><a href="?page={{ c_page|add:+1 }}" aria-label="Next">下一页</a></li>
  {% endif %}
  

  </ul>
  
</nav>
  

  
</body>
  
</html>
  

显示限定页码数
  如果页数过多怎么办?这里保持只显示10个页码
  将template中的paginator.page_range(总页数的列表)修改为下面的pageRange,
  因为显示页数过多,我们这里指定返还给template的页码数列表(range)
  def index(request):
  

book_list=Book.objects.all()  

  
paginator = Paginator(book_list, 2)
  
page = request.GET.get('page',1)
  
currentPage=int(page)
  

  
#如果总页数大于30
  
if paginator.num_pages>30:
  #如果当前页面page的值-5还小于1
  if currentPage-5<1:
  #页码的列表为1-10(pageRange返回给模板)
  pageRange=range(1,11)
  #如果当前页面page的值+5大于总页数
  elif currentPage+5>paginator.num_pages:
  #计算最大页数-10页的页码
  min_page = (paginator.num_pages + 1) - 10
  #计算当前页面所需要减去的页码数
  page_num = currentPage - min_page
  #页码的列表为“当前所在页数-上面计算的页数 至 总页数+1”,正好凑齐10页(pageRange返回给模板)
  pageRange=range(currentPage-page_num,paginator.num_pages+1)
  

  else:
  #页码的列表为“当前所在页数-5,到当前所在页数+5”(pageRange返回给模板)
  pageRange=range(currentPage-5,currentPage+5)
  

  
else:
  #如果总页数小于30,返回给模板实际的页码的列表
  pageRange=paginator.page_range
  

  
try:
  #获取当前页面对象
  book_list = paginator.page(page)
  
except PageNotAnInteger:
  book_list = paginator.page(1)
  
except EmptyPage:
  book_list = paginator.page(paginator.num_pages)
  

  
return render(request,"index.html",locals())
  



中间件

  中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。
  因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
  如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。

自定义中间件
  中间件中一共有四个方法:

  process_request
  process_view
  process_exception
  process_response


process_request,process_response
  当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,
  views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者

  上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin
  settings
  自定义中间件放在哪都可以
  

MIDDLEWARE = [  '...Django默认的Middleware...'
  'app01.utils.mymiddlewares.M1',#注意,不要忘了逗号
  'app01.utils.mymiddlewares.M2'
  
]
  

  in views:
  

from django.shortcuts import render, HttpResponse  

  
def index(request):
  print("index")
  return HttpResponse("OK")
  

  in Mymiddlewares.py:
  

from django.utils.deprecation import MiddlewareMixin  

  
from django.shortcuts import HttpResponse
  

  
class M1(MiddlewareMixin):   #注意继承MiddlewareMixin类
  def process_request(self, request):
  print("M1 process_request")
  

  def process_response(self, request, response):
  print("M1 process_response")
  return response      #process_response要返回一个response
  

  
class M2(MiddlewareMixin):
  def process_request(self, request):
  print("M2 process_request")
  

  def process_response(self, request, response):
  print("M2 process_response")
  return response
  

  结果
  

M1 process_request  
M2 process_request
  
index
  
M2 process_response
  
M1 process_response
  

  注意,process_request带有return的情况下会在满足条件时原路返回,等于从中间拦截了,不再往下走。
  如果 process_response的return不返回response而且是它的,同样也会产生偷梁换柱的效果,返回给客户端的结果将不会是 views中定义的结果

Django-form表单

数据校验
  首先在模板中创建一个简单的表单,以获得用户名、邮箱、手机号等
  

<form action="" method="post" novalidate>  {% csrf_token %}
  <p>用户名 <input type="text" name="user"></p>
  <p>邮箱 <input type="email" name="email"></p>
  <p>手机号 <input type="text" name="tel"></p>
  <input type="submit">
  
</form>
  

  此时我们要将用户在网页上填写的内容在视图中拿出来,并做判断
  之前我们是使用if request.POST.get取出后进行判断的,这里换成form表单,
  方法就是在views新建一个Form类(需要继承forms.Form)
  views:
  

from django import forms  

  
class UserForm(forms.Form):
  user=forms.CharField(min_length=5)#最少5位
  tel=forms.CharField(max_length=8)   #最长不超过8位
  email=forms.EmailField()            #判断是否是邮箱地址类型
  

  
#我们通过上面这个类帮助我们进行数据校验,从而实现功能的分离和复用
  
def reg(request):
  

  if request.method == "POST":
  form = UserForm(request.POST) #绑定数据至表单
  if form.is_valid(): 如果form.is_valid()为Ture
  return HttpResponse('OK')
  else:
  return render(request, 'reg.html', {"form": form})
  

  return render(request, 'reg.html')
  

  表单的is_valid()方法,如果被校验的字段有一个错误,那么就会返回False
  备注:
  

在表单中输入内容,看print(request.POST)能打印出什么  
<QueryDict: {
  'csrfmiddlewaretoken': ['Mhzbi6hiHnxVAKG9GEChEzscCo5GUnkuBnH3xmVOQGYfXxCTQUcoCiu9hGIiqRRT'],
  'user': ['dzm'],
  'email': ['335@qq.com'],
  'tel': ['1118']
  }>
  

form表单数据校验原理
  会生成两个字典
  

form.is_valid():  # 校验成功的字段
  form.cleaned_data={"user":"alex999","tel":'123'}
  

  # 校验失败的字段
  form.errors={"email":["..........","......."]} #列表中是错误信息,不再保留key原本的值
  

  可以将他们打印出来
  print(&quot;====>&quot;,form.cleaned_data)
  print(&quot;====>&quot;,form.errors)
  其它
  print(&quot;---->&quot;, type(form.errors[&quot;user&quot;]))#实际是个字典
  print(&quot;---->&quot;, form.errors[&quot;user&quot;])#这样可以取出具体的错误,然后返回给模板通过{{ form.errors.user.0 }}显示出来

渲染标签
  form除了做校验用还可以做标签用(先拿到一个未绑定数据的form),生成的每个input标签就是form类中字段的名字
  views:
  

class UserForm(forms.Form):  user = forms.CharField(
  label="用户名",   #自定义form表单显示到网页的名字
  min_length=5,
  error_messages={"required": "不能为空", "min_length": "最小长度不能小于5"},#自定义错误提示信息
  widget=widgets.TextInput(attrs={"class":"form-clontrol"})#自定义属性,添加一个Bootstrap样式
  )
  

  tel=forms.CharField(label="手机号", max_length=8, widget=widgets.TextInput(attrs={"class": "form-control"}))
  email=forms.EmailField(label="邮箱", widget=widgets.TextInput(attrs={"class": "form-control"}))
  

  

Widgets
  每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单Widget,例如<input type=&quot;text&quot;>。
  在大部分情况下,字段都具有一个合理的默认Widget。例如,默认情况下,CharField 具有一个TextInput Widget,它在HTML 中生成一个<input type=&quot;text&quot;>

表单渲染的选项
  对于<label>/<input> 对,还有几个输出选项:

  {{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
  {{ form.as_p }} 将它们渲染在<p> 标签中
  {{ form.as_ul }} 将它们渲染在<li> 标签中
  注意,你必须自己提供<table> 或<ul> 元素。

  模板:
  {#方案1#}
  

{#<form action="" method="post" novalidate>#}  
{#    {% csrf_token %}#}
  
{#    {{ form.as_p }}#}
  
{##}
  
{#    <input type="submit">#}
  
{#</form>#}
  

  {#方案2#}
  

{#<form action="" method="post" novalidate>#}  
{#    {% csrf_token %}#}
  
{#    <div>#}
  
{#      用户名#}
  
{#      {{ form.user }}#}
  
{#    </div>#}
  
{##}
  
{#    <div>#}
  
{#      邮箱#}
  
{#      {{ form.email }}#}
  
{#    </div>#}
  
{#      <div>#}
  
{#      手机号#}
  
{#      {{ form.tel }}#}
  
{#    </div>#}
  
{#    #}
  
{#    <input type="submit">#}
  
{#</form>#}
  

  方案3
  

<div>  <div>
  <div>
  <form action="" method="post" novalidate>
  {% csrf_token %}
  {% for filed in form %}
  <div>
  <label for="">{{ filed.label }}</label>
  {{ filed }}
  </div>
  {% endfor %}
  <input type="submit">
  </form>
  </div>
  </div>
  
</div>
  
</body>
  
</html>
  

  更多内容:http://www.cnblogs.com/yuanchenqi/articles/7614921.html

用户认证
  用户认证基于session,
  用户信息存储在auth_user表中,
  在命令行新建超级用户:(manage.py)
  createsuperuser

用户登录
  

def login(request):  

  if request.method == "POST":
  user = request.POST.get("user")
  pwd = request.POST.get("pwd")
  

  #校验,将获取到的用户名和密码与auth_user表中的记录做比对,此时会将password转换成加密信息再比对
  user = auth.authenticate(username=user, password=pwd)
  #如果比对成功会返回一个User对象,失败user会得到一个None
  

  if user:
  #可以获得一个request.user对象,这个对象可以取到当前user对象所代表的用户的所有信息
  auth.login(request, user)

  #此函数使用django的session框架给某个已认证的用户附加上session>  

  return redirect("/index/")
  else:
  return redirect("/login/")
  

  return render(request, "login.html")
  

状态保存验证
  

def index(request):  if not request.user:
  return redirect("/login/")
  

  #使用request.user获取用户名
  name = request.user.username
  return render(request, "index.html", {"name":name})
  

  
## 注销
  
def logout(request):
  #这句话的本质还是调用request.session.flush()
  auth.logout(request)
  #当调用该函数时,当前请求的session信息会全部清除
  

  return redirect("/login/")
  

注册(创建用户)
  

def reg(request):  if request.method == "POST":
  user = request.POST.get("user")
  pwd = request.POST.get("pwd")
  

  #create_user创建一个普通用户,
  User.objects.create_user(username=user, password=pwd)
  return redirect("/login/")
  

  return render(request, "reg.html")
页: [1]
查看完整版本: Python Day18 Django 04