西游之路——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组件详情:稍后更新

原文地址:https://www.cnblogs.com/Lujun1028/p/9737857.html

时间: 2024-08-04 16:26:37

西游之路——python全栈——通用模块(pager、check_code、form验证)的相关文章

西游之路——python全栈——Django~1

知识预览 Django基本命令 二 路由配置系统(URLconf) 三 编写视图 四 Template 五 数据库与ORM admin的配置 一 什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端.   最简单的Web应用就是先把HTML用文件保存好,用一个现

西游之路——python全栈——自定义用户认证

django自定义用户认证(使用自定义的UserProfile,而不是django自带的),就需要(django要求)将为UserProfile单独创建一个app,这个app啥也不干,就是为UserProfile而生的; 这里我们创建一个app,名字叫做custom_auth,事实上,我们只需要对其中的models文件和admin.py做操作就可以了; 第一步:  创建user model 下面是models.py文件的内容: 1 from django.utils.safestring imp

西游之路——python全栈——django中models配置

目录 Django支持多种数据库,sqlite,mysql,oracle等,其默认数据库是sqlite 在settings文件中可以发现: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } 其默认数据库是sqlite3 要想使用其他数据库,需要修改相应的引擎和配置 (1)sqlite: 'ENGINE': 'dja

西游之路——python全栈——Form组件字段及动态绑定

一.HTML中 | safe  可在后台用以下方式处理 1 text = "<input type'text' />" 2 from django.utils.safestring import mark_safe 3 text = mark_safe(text) 二.views.py操作 1 from django.shortcuts import render 2 3 from django import forms 4 from django.forms import

西游之路——python全栈——瀑布流

############################### class Picture(models.Model): src = models.ImageField(verbose_name='图片路径', upload_to='./static/images/picture/') title = models.CharField(verbose_name='标题', max_length=32) summary = models.CharField(verbose_name='简介', m

西游之路——python全栈——报障系统之后台管理

一.后台管理页面布局 1.用户: - 普通用户 知识库+提交报账单+个人信息 - 管理员 知识库+提交报账单+个人信息+处理报账单 - 超级管理员 知识库+提交报账单+个人信息+处理报账单+报障统计信息 权限管理2.菜单: - 知识库管理 文章 标签 分类 - 报障管理 个人报障 报障处理 报障统计信息 - 权限管理 菜单 权限 角色 二.公共模板及路由分发 1.后台菜单栏.导航栏 1 <!DOCTYPE html> 2 <html lang="en"> 3 &

西游之路——python全栈——ORM之SQLAlchemy(1)

目录 定义一个类,ORM(对象关系映射)将这个类转换为sql语句,使用pymysql进行执行 一,底层处理 使用engine/connectionpooling/dialect进行数据库操作,engine使用connectionpooling连接数据库,然后在通过dialect执行sql语句(SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API) pymysql mysql+pymysql:/

西游之路——python全栈——ORM之SQLAlchemy(3)外键与relationship的关系

目录 relationship是为了简化联合查询join等,创建的两个表之间的虚拟关系,这种关系与标的结构时无关的.他与外键十分相似,确实,他必须在外键的基础上才允许使用 不然会报错: sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Father.son - there are no foreign keys link

Python全栈开发——模块导入

#模块 1.导入模块 import module from module import *                不推荐(不用) from module import 函数 #导入自定义模块 特点 1.import module(自己定义的模块)                                       只能导入自己定义在同一目录下的模块 2.from file_name(文件名(同一运行文件下的文件)) import module(自己定义的模块)      可导入同