赞
踩
第九章 sweetalert前端插件、序列化组件、批量数据操作、分页器、Forms组件(上)
serializers是django自带的序列化数据的组件
使用JsonResponse来转化数据发送到前端
data_list = [] # [{}, {}, {}] 将json数据只作为列表套字典类型的 user_queryset = models.User.objects.all()# 对于QuerySet格式的数据是无法序列化的 for user_obj in user_queryset: data_list.append({ 'uid':user_obj.uid, 'username':user_obj.username, 'password':user_obj.password, }) return JsonResponse(data_list,safe=False) """ 使用jsonresponse可以高度定制我们需要的数据类型,缺点是数据多时使用麻烦 [{ "uid": 1, "username": "asdasd", "password": "123123" }, { "uid": 2, "username": "zxczxc", "password": "123123" },... ] """
使用serializers来进行json序列化
user_queryset = models.User.objects.all() ret = serializers.serialize('json', user_queryset) # 使用 return HttpResponse(ret) """使用serializers可以快速生成json数据,格式也是固定的 [{ "model": "app01.user", 数据所属的表 "pk": 1, 数据主键 "fields": { 具体的数据 "username": "asdasd", "password": "123123" } }, { "model": "app01.user", "pk": 2, "fields": { "username": "zxczxc", "password": "123123" } }, ... ] """
django插入数据到数据库是很慢的,当我们一口气需要插入很多数据时需要优化数据的插入。
django插入数据通过models中的类进行的,所以我们先将数据转化为对应的类,可以大大节省django插入数据库时的转化对应表对象的过程,从而大大节省插入数据时间
def add_data(request):
user_list = []
for i in range(100000):
# 先用类产生一个对象
source_book_obj = models.User(username=f'username{i}',password=f'password{i}')
# 将对象追加到列表中
user_list.append(source_book_obj)
models.User.objects.bulk_create(user_list) # 批量插入
user_queryset = models.User.objects.all()
return render(request, 'add_data.html', locals())
前端不可能将所有的数据全部展示到一页,应该考虑使用分页,每页展示一些,前端很多地方都需要分页所以有了分页的模块。
此处提供的自定义分页器模块需要搭配bootstrap来使用,也可以自行修改分页器和内容显示区域的样式
首先创建一个utils包
创建一个py文件在其中添加以下代码
class Pagination(object): def __init__(self, current_page, all_count, per_page_num=2, pager_count=11): """ 封装分页相关数据 :param current_page: 当前页 :param all_count: 数据库中的数据总条数 :param per_page_num: 每页显示的数据条数 :param pager_count: 最多显示的页码个数 """ try: current_page = int(current_page) except Exception as e: current_page = 1 if current_page < 1: current_page = 1 self.current_page = current_page self.all_count = all_count self.per_page_num = per_page_num # 总页码 all_pager, tmp = divmod(all_count, per_page_num) if tmp: all_pager += 1 self.all_pager = all_pager self.pager_count = pager_count self.pager_count_half = int((pager_count - 1) / 2) @property def start(self): return (self.current_page - 1) * self.per_page_num @property def end(self): return self.current_page * self.per_page_num def page_html(self): # 如果总页码 < 11个: if self.all_pager <= self.pager_count: pager_start = 1 pager_end = self.all_pager + 1 # 总页码 > 11 else: # 当前页如果<=页面上最多显示11/2个页码 if self.current_page <= self.pager_count_half: pager_start = 1 pager_end = self.pager_count + 1 # 当前页大于5 else: # 页码翻到最后 if (self.current_page + self.pager_count_half) > self.all_pager: pager_end = self.all_pager + 1 pager_start = self.all_pager - self.pager_count + 1 else: pager_start = self.current_page - self.pager_count_half pager_end = self.current_page + self.pager_count_half + 1 page_html_list = [] # 添加前面的nav和ul标签 page_html_list.append(''' <nav aria-label='Page navigation>' <ul class='pagination'> ''') first_page = '<li><a href="?page=%s">首页</a></li>' % (1) page_html_list.append(first_page) if self.current_page <= 1: prev_page = '<li class="disabled"><a href="#">上一页</a></li>' else: prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,) page_html_list.append(prev_page) for i in range(pager_start, pager_end): if i == self.current_page: temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,) else: temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,) page_html_list.append(temp) if self.current_page >= self.all_pager: next_page = '<li class="disabled"><a href="#">下一页</a></li>' else: next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,) page_html_list.append(next_page) last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,) page_html_list.append(last_page) # 尾部添加标签 page_html_list.append(''' </nav> </ul> ''') return ''.join(page_html_list)
视图函数:
from utils import mypage # 导入刚才创建的py文件
user_queryset = models.User.objects.all()
# 1.产生分页器对象
'''针对于Pagination有以下几个关键字参数
current_page: 当前页
all_count: 数据库中的数据总条数
per_page_num: 每页显示的数据条数
pager_count: 最多显示的页码个数
'''
page_obj = mypage.Pagination(current_page=request.GET.get('page'),all_count=user_queryset.count())
# 2.产生分页数据对象
page_queryset = user_queryset[page_obj.start:page_obj.end]
return render(request,'many_data.html',locals())
显示层:
注意导入bootstrap
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{% for user in page_queryset %}
<p>{{ user.username }}</p>
<p>{{ user.password }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
</div>
</div>
</div>
django提供的forms组件可以实现快速产生获取数据的标签、数据验证、错误信息的反馈
编写自己的Forms
参数 | 作用 |
---|---|
min_length | 字符串最小长度 |
max_length | 字符串最大长度 |
min_value | 数字最小位数 |
max_value | 数字最大位数 |
label | 对应的label值 |
required | 验证时可以为空 |
from django import forms
class MyForm(forms.Form):
# 用户名至少三个字符最多八个字符
username = forms.CharField(min_length=3,max_length=8, label="用户名")
# 密码最小不能小于4 最大不能超过16
password = forms.CharField(min_length=6,max_length=16, label="密码")
# 邮箱必须符合邮箱格式(@关键符号)
email = forms.EmailField(required=True, label="邮箱")
data = request.POST
# 1.将数据传入实例化对象
form_obj = MyForm({"username":data.get('username'), "password":data.get('password'), "email":data.get('email')}) # 放入对应的字典数据 可以使用 **data 直接传入
# 2.查看数据是否合法(全部合法结果才是True)
form_obj.is_valid()
# 3.查看不符合条件的数据及原因
form_obj.errors # 类似这种 {'email': ['Enter a valid email address.']}
# 4.查看符合条件的数据
form_obj.cleaned_data # 符合条件的数据 {'username': 'kdq', 'password': k12345}
forms组件只负责渲染获取用户数据的标签
form表单标签和提交按钮需要自己写
封装程度高 扩展性较差 主要用于快速生成页面测试功能
{{ form_obj.as_p }} {# 这种注释中label和input会渲染在p标签中 #}
通过下图可以看出label和input在p中
错误信息在ul li中
{{ form_obj.as_table }} <!-- 这种注释中lable和input直接渲染 -->
通过下图可可以看出label和input直接渲染
错误信息在ul li中
{{ form_obj.as_ul }} {# label和input渲染在li中 #}
通过下图可可以看出label和input渲染在li中
错误信息在li下的ul li中
封装程度低 扩展性较好 但是字段比较多的情况下不方便
此时form_obj.username.label获取的只是对应input的label文本需要自行定制样式
form_obj.username将会渲染出input
<form action="" method="post">
<div class="form-group">
<label for="">{{ form_obj.username.label }}</label>
{{ form_obj.username }}
</div>
<div class="form-group">
<label for="">{{ form_obj.password.label }}</label>
{{ form_obj.password }}
</div>
<div class="form-group">
<label for="">{{ form_obj.email.label }}</label>
{{ form_obj.email }}
</div>
<button type="submit" id="logobtn" class="btn btn-default">登录</button>
</form>
高度定制化,同时可以使用模板语法快速渲染
<form action="" method="post">
{% for form in form_obj %}
<div class="form-group">
<label>{{ form.label }}</label>
{{ form }}
</div>
{% endfor %}
<button type="submit" id="logobtn" class="btn btn-default">登录</button>
</form>
forms类中填写的校验性参数前端浏览器会识别并添加校验操作,前端的验证操作是可以被轻易修改的,最好是在后端验证
form表单可以取消浏览器自动添加校验功能的操作
<form action="" method="post" novalidate></form> {# 只要添加novalidate就能不触发forms组件的验证 #}
错误信息的前端获取方式
{{ form.errors.0 }}
提示信息可以自定义
在对应字段中设置error_messages即可
from django import forms
class MyForm(forms.Form):
# 用户名至少三个字符最多八个字符
username = forms.CharField(min_length=3,max_length=8, label="用户名", error_messages={
'min_length':'用户名最短3位',
'max_length':'用户名最长8位',
'required':'用户名必填'
})
# 密码最小不能小于4 最大不能超过16
password = forms.CharField(min_length=6,max_length=16, label="密码")
# 邮箱必须符合邮箱格式(@关键符号)
email = forms.EmailField(required=True, label="邮箱")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。