Django进阶

Form django中的Form一般有两种功能:

输入html

验证用户输入

import re
from django import forms
from django.core.exceptions import ValidationError
def mobile_validate(value):
   mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
   if not mobile_re.match(value):
       raise ValidationError('手机号码格式错误')

class PublishForm(forms.Form):
   user_type_choice = (
       (0, u'普通用户'),
       (1, u'高级用户'),
   )
   user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                 attrs={'class': "form-control"}))
   title = forms.CharField(max_length=20,
                           min_length=5,
                           error_messages={'required': u'标题不能为空',
                                           'min_length': u'标题最少为5个字符',
                                           'max_length': u'标题最多为20个字符'},
                           widget=forms.TextInput(attrs={'class': "form-control",
                                                         'placeholder': u'标题5-20个字符'}))

   memo = forms.CharField(required=False,
                          max_length=256,
                          widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3}))

   phone = forms.CharField(validators=[mobile_validate, ],
                           error_messages={'required': u'手机不能为空'},
                           widget=forms.TextInput(attrs={'class': "form-control",
                                                         'placeholder': u'手机号码'}))

   email = forms.EmailField(required=False,
                           error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                           widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))


def publish(request):
   ret = {'status': False, 'data': '', 'error': '', 'summary': ''}
   if request.method == 'POST':
       request_form = PublishForm(request.POST)
       if request_form.is_valid():
           request_dict = request_form.clean()
           print request_dict
           ret['status'] = True
       else:
           error_msg = request_form.errors.as_json()
           ret['error'] = json.loads(error_msg)
   return HttpResponse(json.dumps(ret))
复制代码

在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义

class AdminModelForm(forms.ModelForm):
   class Meta:
       model = models.Admin
       #fields = '__all__'
       fields = ('username', 'email')
       widgets = {
           'email' : forms.PasswordInput(attrs={'class':"alex"}),
       }
复制代码

跨站请求伪造 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

应用

1、普通表单

veiw中设置返回值: return render(request, 'xxx.html', data) html中设置Token:   {% csrf_token %}

2、Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

views.py

from django.shortcuts import render,HttpResponse
from django.template.context import RequestContext
# Create your views here.
def test(req):
   if req.method == 'POST':
       print(req.POST.get('username'))
       print(req.POST.get('pwd'))
       return HttpResponse("ok")
   return render(req,'h1.html')

html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="/static/jquery-3.3.1.min.js"></script>
</head>
<body>
       <input type="text" name="username" id="u"><br>
       <input type="text" name="pwd" id="p">
       <input type="button" value="提交" onclick="f1()">
<script>
   $.ajaxSetup({
       data: {
           csrfmiddlewaretoken: '{{ csrf_token }}'
       },
   });
   function f1() {
       $.ajax({
           url:'/test/',
           type:'post',
           data:{
               username:$('#u').val(),
               pwd:  $('#p').val()
           },
           success:function (data) {
               console.log(data)
           }
       });
   }
</script>

</body>
</html>
复制代码

Cookie 1、获取Cookie:

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
   参数:
       default: 默认值
          salt: 加密盐
       max_age: 后台控制过期时间
复制代码

2、设置Cookie:

rep = HttpResponse(...) 或 rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
   参数:
       key,              键
       value='',         值
       max_age=None,     超时时间
       expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
       path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
       domain=None,      Cookie生效的域名
       secure=False,     https传输
       httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
复制代码

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });
复制代码

Session Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认)

缓存

文件

缓存+数据库

加密cookie

缓存Session

a. 配置 settings.py
   SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
   SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
   SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
   SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
   SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
   SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
   SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
   SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
   SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
   SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
复制代码

b. 使用

def index(request):
       # 获取、设置、删除Session中数据
       request.session['k1']
       request.session.get('k1',None)
       request.session['k1'] = 123
       request.session.setdefault('k1',123) # 存在则不设置
       del request.session['k1']
       # 所有 键、值、键值对
       request.session.keys()
       request.session.values()
       request.session.items()
       request.session.iterkeys()
       request.session.itervalues()
       request.session.iteritems()
       # 用户session的随机字符串
       request.session.session_key

       # 将所有Session失效日期小于当前日期的数据删除
       request.session.clear_expired()

       # 检查 用户session的随机字符串 在数据库中是否
       request.session.exists("session_key")

       # 删除当前用户的所有Session数据
       request.session.delete("session_key")

       request.session.set_expiry(value)
           * 如果value是个整数,session会在些秒数后失效。
           * 如果value是个datatime或timedelta,session就会在这个时间后失效。
           * 如果value是0,用户关闭浏览器session就会失效。
           * 如果value是None,session会依赖全局session失效策略。
复制代码

分页 Django内置分页

views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
L = []
for i in range(999):
   L.append(i)
def index(request):
   current_page = request.GET.get('p')

   paginator = Paginator(L, 10)
   # per_page: 每页显示条目数量
   # count:    数据总个数
   # num_pages:总页数
   # page_range:总页数的索引范围,如: (1,10),(1,200)
   # page:     page对象
   try:
       posts = paginator.page(current_page)
       # has_next              是否有下一页
       # next_page_number      下一页页码
       # has_previous          是否有上一页
       # previous_page_number  上一页页码
       # object_list           分页之后的数据列表
       # number                当前页
       # paginator             paginator对象
   except PageNotAnInteger:
       posts = paginator.page(1)
   except EmptyPage:
       posts = paginator.page(paginator.num_pages)
   return render(request, 'index.html', {'posts': posts})


Html

<!DOCTYPE html>
<html>
<head lang="en">
   <meta charset="UTF-8">
   <title></title>
</head>
<body>
<ul>
   {% for item in posts %}
       <li>{{ item }}</li>
   {% endfor %}
</ul>
<div class="pagination">
     <span class="step-links">
       {% if posts.has_previous %}
           <a href="?p={{ posts.previous_page_number }}">Previous</a>
       {% endif %}
         <span class="current">
           Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
         </span>
         {% if posts.has_next %}
             <a href="?p={{ posts.next_page_number }}">Next</a>
         {% endif %}
     </span>
</div>
</body>
</html>
Html
复制代码

自定义分页

分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

4、在数据表中根据起始位置取值,页面上输出数据

需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、设定显示多少页号

4、获取当前数据总条数

5、根据设定显示多少页号和数据总条数计算出,总页数

6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

7、在数据表中根据起始位置取值,页面上输出数据

8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

分页实例

#!/usr/bin/env python
# _*_coding:utf-8_*_
from django.utils.safestring import mark_safe

class PageInfo(object):
   def __init__(self,current,totalItem,peritems=5):
       self.__current=current
       self.__peritems=peritems
       self.__totalItem=totalItem
   def From(self):
       return (self.__current-1)*self.__peritems
   def To(self):
       return self.__current*self.__peritems
   def TotalPage(self):  #总页数
       result=divmod(self.__totalItem,self.__peritems)
       if result[1]==0:
           return result[0]
       else:
           return result[0]+1

def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数
   perPager=11
   #总页数<11
   #0 -- totalpage
   #总页数>11
       #当前页大于5 currentPage-5 -- currentPage+5
           #currentPage+5是否超过总页数,超过总页数,end就是总页数
       #当前页小于5 0 -- 11
   begin=0
   end=0
   if totalpage <= 11:
       begin=0
       end=totalpage
   else:
       if currentPage>5:
           begin=currentPage-5
           end=currentPage+5
           if end > totalpage:
               end=totalpage
       else:
           begin=0
           end=11
   pager_list=[]
   if currentPage<=1:
       first="<a href=''>首页</a>"
   else:
       first="<a href='%s%d'>首页</a>" % (baseurl,1)
   pager_list.append(first)

   if currentPage<=1:
       prev="<a href=''>上一页</a>"
   else:
       prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
   pager_list.append(prev)

   for i in range(begin+1,end+1):
       if i == currentPage:
           temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
       else:
           temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
       pager_list.append(temp)
   if currentPage>=totalpage:
       next="<a href='#'>下一页</a>"
   else:
       next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
   pager_list.append(next)
   if currentPage>=totalpage:
       last="<a href=''>末页</a>"
   else:
       last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
   pager_list.append(last)
   result=''.join(pager_list)
   return mark_safe(result)   #把字符串转成html语言
复制代码

识别图中二维码,领取python全套视频资料
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值