• 西游之路——python全栈——通用模块(pager、check_code、form验证)


    1、验证码

     1 import random
     2 from PIL import Image, ImageDraw, ImageFont, ImageFilter
     3 
     4 _letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
     5 _upper_cases = _letter_cases.upper()  # 大写字母
     6 _numbers = ''.join(map(str, range(3, 10)))  # 数字
     7 init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
     8 
     9 
    10 def create_validate_code(size=(120, 30),
    11                          chars=init_chars,
    12                          img_type="GIF",
    13                          mode="RGB",
    14                          bg_color=(238, 99, 99),
    15                          fg_color=(0, 0, 255),
    16                          font_size=18,
    17                          font_type="Monaco.ttf",
    18                          length=4,
    19                          draw_lines=True,
    20                          n_line=(1, 2),
    21                          draw_points=True,
    22                          point_chance=2):
    23     """
    24     @todo: 生成验证码图片
    25     @param size: 图片的大小,格式(宽,高),默认为(120, 30)
    26     @param chars: 允许的字符集合,格式字符串
    27     @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
    28     @param mode: 图片模式,默认为RGB
    29     @param bg_color: 背景颜色,默认为白色
    30     @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
    31     @param font_size: 验证码字体大小
    32     @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
    33     @param length: 验证码字符个数
    34     @param draw_lines: 是否划干扰线
    35     @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
    36     @param draw_points: 是否画干扰点
    37     @param point_chance: 干扰点出现的概率,大小范围[0, 100]
    38     @return: [0]: PIL Image实例
    39     @return: [1]: 验证码图片中的字符串
    40     """
    41     width, height = size  # 宽高
    42     # 创建图形
    43     img = Image.new(mode, size, bg_color)
    44     draw = ImageDraw.Draw(img)  # 创建画笔
    45 
    46     def get_chars():
    47         """生成给定长度的字符串,返回列表格式"""
    48         return random.sample(chars, length)
    49 
    50     def create_lines():
    51         """绘制干扰线"""
    52         line_num = random.randint(*n_line)  # 干扰线条数
    53         for i in range(line_num):
    54             # 起始点
    55             begin = (random.randint(0, size[0]), random.randint(0, size[1]))
    56             # 结束点
    57             end = (random.randint(0, size[0]), random.randint(0, size[1]))
    58             draw.line([begin, end], fill=(0, 0, 0))
    59 
    60     def create_points():
    61         """绘制干扰点"""
    62         chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]
    63         for w in range(width):
    64             for h in range(height):
    65                 tmp = random.randint(0, 100)
    66                 if tmp > 100 - chance:
    67                     draw.point((w, h), fill=(0, 0, 0))
    68 
    69     def create_strs():
    70         """绘制验证码字符"""
    71         c_chars = get_chars()
    72         strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开
    73         font = ImageFont.truetype(font_type, font_size)
    74         font_width, font_height = font.getsize(strs)
    75 
    76         draw.text(((width - font_width) / 3, (height - font_height) / 3),
    77                   strs, font=font, fill=fg_color)
    78 
    79         return ''.join(c_chars)
    80 
    81     if draw_lines:
    82         create_lines()
    83     if draw_points:
    84         create_points()
    85     strs = create_strs()
    86     # 图形扭曲参数
    87     params = [1 - float(random.randint(1, 2)) / 100,
    88               0,
    89               0,
    90               0,
    91               1 - float(random.randint(1, 10)) / 100,
    92               float(random.randint(1, 2)) / 500,
    93               0.001,
    94               float(random.randint(1, 2)) / 500
    95               ]
    96     img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲
    97     img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)
    98     return img, strs
    check_code.py

    需要配合 MONACO.TTF 字体使用

    2、分页

     1 class Pagination(object):
     2     def __init__(self,totalCount,currentPage,CurentUrl,perPageItemNum=3,maxPageNum=3,):
     3         # 所有数据总个数
     4         self.total_count = int(totalCount)
     5         # 当前页
     6         try:
     7             v = int(currentPage)
     8             if v <= 0:
     9                 v = 1
    10             self.current_page = v
    11 
    12         except Exception as e:
    13             self.current_page = 1
    14         # 每页显示行数
    15         self.per_page_item_num = int(perPageItemNum)
    16         # 最多页面数
    17         self.max_page_num = int(maxPageNum)
    18         self.current_url = CurentUrl
    19 
    20     def start(self):
    21         return (self.current_page - 1)*self.per_page_item_num
    22 
    23     def end(self):
    24         return self.current_page*self.per_page_item_num
    25 
    26     @property
    27     def num_pages(self):
    28         a,b = divmod(self.total_count,self.per_page_item_num)
    29         if b == 0:
    30             return a
    31         return a+1
    32 
    33     @property
    34     def pager_num_range(self):
    35         # 当前页
    36         # self.current_page
    37         # 最多显示页码数 7
    38         # self.per_page_num
    39         # 总页数
    40         # self.num_pages
    41         # 判断最小极值
    42         if self.max_page_num > self.num_pages:
    43             # 根据当前页动态生成,设置页面显示数
    44             return range(1, self.num_pages + 1)
    45         # 总页数特别多时
    46         part = int(self.max_page_num/2)
    47 
    48         if part >= self.current_page:
    49             return range(1, self.max_page_num + 1)
    50 
    51         # 判断最大极值
    52         if (self.current_page + part) >= self.num_pages:
    53             return range(self.num_pages - self.max_page_num + 1, self.num_pages + 1)
    54 
    55         return range(self.current_page - part, self.current_page + part +1)
    56 
    57     def page_str(self):
    58         page_list = []
    59 
    60         if self.current_page ==1:
    61             prev = "<li><a href='#'>上一页</a></li>"
    62         else:
    63             prev = "<li><a href='%s?p=%s'>上一页</a></li>" %(self.current_url,self.current_page-1)
    64         page_list.append(prev)
    65 
    66         first = "<li><a href='%s?p=1'>首页</a></li>" % self.current_url
    67         page_list.append(first)
    68 
    69         for i in self.pager_num_range:
    70             if self.current_page == i:
    71                 tem = "<li class='active'><a href='%s?p=%s'>%s</a></li>" % (self.current_url, i,i)
    72             else:
    73                 tem = "<li><a href='%s?p=%s'>%s</a></li>" % (self.current_url, i, i)
    74             page_list.append(tem)
    75 
    76         last = "<li><a href='%s?p=%s'>尾页</a></li>" % (self.current_url, self.num_pages)
    77         page_list.append(last)
    78 
    79         if self.current_page == self.num_pages:
    80             nex = "<li><a href='#'>下一页</a>"
    81         else:
    82             nex = "<li><a href='%s?p=%s'>下一页</a></li>" % (self.current_url, self.current_page + 1)
    83         page_list.append(nex)
    84 
    85         return ''.join(page_list)
    pager.py

    使用时需要传入三个参数

      - 信息总数

      - 当前页

      - 当前url

    1 obj_list = Pagination(article_list.count(), current_page, current_url)
    2     data_list = article_list[obj_list.start():obj_list.end()]
    视图函数中代码

    3、form验证

      1 from django import forms
      2 from django.forms import fields,widgets
      3 from repository import models
      4 from django.core.exceptions import ValidationError
      5 
      6 class RegisterForm(forms.Form):
      7     username = fields.CharField(
      8         label='用户名',
      9         required=True,
     10         max_length=32,
     11         initial='请输入用户名',
     12         error_messages={
     13             'required': '用户名不能为空',
     14             'min_length': '用户名过短',
     15             'invalid': '格式错误',
     16         }
     17     )
     18     password = fields.CharField(
     19         label='密码',
     20         required=True,
     21         max_length=32,
     22         min_length=6,
     23         error_messages={
     24             'required': '密码不能为空',
     25             'min_length': '密码长度太短',
     26             'invalid': '格式有误',
     27         }
     28     )
     29     # fields.RegexField()   自定义正则
     30     confirm_pwd = fields.CharField(
     31         label='确认密码',
     32         required=True,
     33         max_length=32,
     34         min_length=6,
     35         error_messages={
     36             'required': '密码不能为空',
     37             'min_length': '密码长度太短',
     38             'invalid': '格式有误',
     39         }
     40     )
     41     email = fields.EmailField(
     42         widget=widgets.EmailInput(attrs={"class":"form-control","placeholder": "输入邮箱"}),
     43         label='邮箱',
     44         required=True,
     45         error_messages={
     46             'required': '不能为空',
     47         }
     48     )
     49     # 注意使用cleaned_data.get('username')取值
     50     def clean_username(self):
     51         ret = models.User.objects.filter(username=self.cleaned_data.get('username'))
     52         if not ret:
     53             return self.cleaned_data.get('username')
     54         else:
     55             raise ValidationError('用户名已存在')
     56 
     57     def clean_password(self):
     58         pwd = self.cleaned_data.get('password')
     59         if not pwd.isdigit():
     60             return self.cleaned_data.get('password')
     61         else:
     62             raise ValidationError('不能全是数字')
     63 
     64     # 验证前后密码是否一致
     65     def clean(self):
     66         password = self.cleaned_data.get('password')
     67         confirm_pwd = self.cleaned_data.get('confirm_pwd')
     68         if confirm_pwd == password:
     69             return self.cleaned_data
     70         else:
     71             raise ValidationError('密码输入不一致')
     72 
     73 class LoginForm(forms.Form):
     74     username = fields.CharField(
     75         label='用户名',
     76         required=True,
     77         max_length=32,
     78         initial='请输入用户名',
     79         error_messages={
     80             'required': '用户名不能为空',
     81         }
     82     )
     83     password = fields.CharField(
     84         label='密码',
     85         required=True,
     86         max_length=32,
     87         min_length=6,
     88         error_messages={
     89             'required': '密码不能为空',
     90         }
     91     )
     92     def clean(self):
     93         user_list = models.User.objects.all().values_list('username','password')
     94         user_list = list(user_list)
     95         login_list = (self.cleaned_data.get('username'),self.cleaned_data.get('password'))
     96         if login_list in user_list:
     97             return self.cleaned_data
     98         else:
     99             raise ValidationError('用户名或密码错误')
    100 
    101 class ArticleForm(forms.Form):
    102     title = fields.CharField(
    103         label='标题',
    104         widget=widgets.TextInput(attrs={'class':'form-control', 'placeholder':'标题5-32个字符'}),
    105         required=True,
    106         min_length=5,
    107         max_length=32,
    108         error_messages={
    109             'required':'不能为空',
    110             'min_length':'标题最少为5个字节',
    111             'max_length':'标题最少为32个字节',
    112         }
    113     )
    114     summary = fields.CharField(
    115         label='简介',
    116         required=True,
    117         widget=widgets.Textarea(attrs={'class':'form-control', 'placeholder':'简介10-64个字符'}),
    118         max_length=32,
    119         min_length=10,
    120         error_messages={
    121             'required':'不能为空',
    122             'min_length':'简介最少为10个字节',
    123             'max_length':'简介最多为64个字节',
    124         }
    125     )
    126     detail = fields.CharField(
    127         label='内容',
    128         required=True,
    129         widget=widgets.Textarea(attrs={'id':'detail','class': 'kind-content', 'placeholder': '简介32-256个字符'}),
    130         max_length=256,
    131         min_length=32,
    132         error_messages={
    133             'required': '不能为空',
    134             'min_length': '简介最少为32个字节',
    135             'max_length': '简介最少为256个字节',
    136         }
    137     )
    138     user_choice = models.User.objects.all().values_list('id','username')
    139     user = fields.IntegerField(
    140         label='作者',
    141         widget=widgets.Select(choices=user_choice, attrs={'class':'form-control'})
    142     )
    143     blog_choice = models.Blog.objects.all().values_list('id','title')
    144     blog = fields.IntegerField(
    145         label='博客',
    146         widget=widgets.Select(choices=blog_choice, attrs={'class':'form-control'})
    147     )
    148     tags_choice = models.Tags.objects.all().values_list('id', 'caption')
    149     tags = fields.IntegerField(
    150         label='标签',
    151         widget=widgets.Select(choices=tags_choice, attrs={'class':'form-control'})
    152     )
    153     category_choice = models.Category.objects.all().values_list('id','caption')
    154     category = fields.IntegerField(
    155         label='分类',
    156         widget=widgets.Select(choices=category_choice, attrs={'class':'form-control'})
    157     )
    158 
    159     def clean(self):
    160         self.cleaned_data['user_id'] = self.cleaned_data.get('user')
    161         self.cleaned_data['tags_id'] = self.cleaned_data.get('tags')
    162         self.cleaned_data['blog_id'] = self.cleaned_data.get('blog')
    163         self.cleaned_data['category_id'] = self.cleaned_data.get('category')
    164         del self.cleaned_data['user']
    165         del self.cleaned_data['tags']
    166         del self.cleaned_data['blog']
    167         del self.cleaned_data['category']
    168         return self.cleaned_data
    169 
    170 class TroubleForm(forms.Form):
    171     title = fields.CharField(
    172         label='标题',
    173         required=True,
    174         widget=widgets.TextInput(attrs={'class':'form-control', 'placeholder':'输入标题5-32个字符'}),
    175         max_length=32,
    176         min_length=5,
    177         error_messages={
    178             'required':'标题不能为空',
    179             'min_length':'标题最少为5个字节',
    180             'invalid':'格式错误',
    181         }
    182     )
    183     detail = fields.CharField(
    184         label='内容',
    185         required=True,
    186         widget=widgets.Textarea(attrs={'id':'detail','class':'kind-content', 'placeholder':'输入内容5-256个字符'}),
    187         max_length=256,
    188         min_length=5,
    189         error_messages={
    190             'required': '内容不能为空',
    191             'min_length': '内容最少为5个字节',
    192             'invalid': '格式错误',
    193         }
    194     )
    注册、登录、编辑、添加

    有关form组件详情:稍后更新

     

  • 相关阅读:
    weblogic10配置JNDI须在JDK1.5上
    JDBC大批量写入数据到SQLServer2000,记录数大于10000
    ASP递归调用:已知节点查找根节点的函数
    window.createPopup()
    Hibernate处理同名实体的方法
    windows下Apache Rewrite .htaccess 设置
    使用jsonlib将java对象转换成json字符串
    关于oracle和jdbc中rowid格式的转化
    [转]MaCfee导致Asp.net/Jmail无法发送邮件的解决办法
    javascript监测(控制 )上传文件大小
  • 原文地址:https://www.cnblogs.com/Lujun1028/p/9737857.html
Copyright © 2020-2023  润新知