批量插入数据,自定义分页器,forms组件,钩子函数,forms组件重要参数,modelform组件

一:批量插入数据

1.urls.py

urlpatterns = [
    # 批量插入数据
    path('index/', views.index)
]

2.views.py

def index(request):
    l = []
    for i in range(10000):
        l.append(models.Book(title='第%s本书' % i))
    models.Book.objects.bulk_create(l)
    return render(request, 'index.html', locals())

3.html页面

<body>
    <div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in l %}
                <P>{{ book.title }}</P>
            {% endfor %}
        </div>
    </div>
</div>
</body>
总结:如何批量插入数据
  • 1.首先自定义一个空的列表
  • 2.把每一条数据通过append方法添加到自定的列表中
  • 3.最后通过bulk_create方法把自定义列表添加到数据库中
补充知识点:

通过bulk_update方法,实现对数据库中数据的批量修改

二:自定义分页器(要会使用)

1.自定义分页器代码

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:  最多显示的页码个数
        
        用法:
        queryset = model.objects.all()
        page_obj = Pagination(current_page,all_count)
        page_data = queryset[page_obj.start:page_obj.end]
        获取数据用page_data而不再使用原始的queryset
        获取前端分页样式用page_obj.page_html
        """
        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)
如何使用自定义分页器
  • 步骤1:首相在应用文件下建一个文件夹(plugins),再在这个文件夹中建一个py文件(mypage.py),把自定义分页器代码粘贴进去
  • 步骤2:在需要分页的视图函数中写入一下代码
def index(request):
	from app01.plugins import mypage
    book_query = models.Book.objects.all()
    page_obj = mypage.Pagination(current_page=request.GET.get('page'),
                                 all_count=book_query.count()
                                 )
    page_query = book_query[page_obj.start:page_obj.end]
    return render(request, 'index.html', locals())
  • 步骤3:在需要分页的html页面中写入以下代码
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book_obj in page_query %}
                <p class="text-center">{{ book_obj.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
    </div>

三:forms组件

1.forms组件具有的功能
  • 1.数据校验:支持提前设置各种校验规则,之后自动校验
  • 2.渲染画面:支持直接渲染获取用户数据的各种标签
  • 3.展示信息:支持针对不同的校验失败,展示不同的提示信息
2.forms类的产生
from django import forms

class MyForms(forms.Form):
    """下面每个字段,都必须要符合括号中的条件,或者forms组件隐藏的特点条件"""
    name = forms.CharField(min_length=3, max_length=8)
    pwd = forms.IntegerField(min_value=3, max_value=8)
    email = forms.EmailField()
3.forms组件之数据校验

直接在pycharm自带的测试工具中测试:

from app01 import models
from app01 import views
form_obj = views.MyForms({'name':'jason','pwd':123,'email':121})

form_obj.is_valid()
False

form_obj.cleaned_data
{'name': 'jason'}

form_obj.errors
{'pwd': ['Ensure this value is less than or equal to 8.'], 'email': ['Enter a valid email address.']}


总结:
  • 1.首先导入要测试的文件
  • 2.准备好测试数据,并且以字典的形式传入,同时生成测试对象
  • 3.object.is_valid() 该方法只有在所有的数据都合法的情况下,才会返回True
  • 4.object.cleaned_data 返回所有符合校验规则的数据
  • 5.object.errors 返回不符合校验规则的数据,以及不符合规则的原因
补充总结:
  • 1.只校验类中出现的字段,多传没影响,不会报错
  • 2.少传会直接报错
4.forms组件之渲染标签
  • 步骤1:写一个视图函数,产生一个forms类的空对象,把这个空对象直接传到html页面上
def index1(request):
    # 1.先产生一个空对象
    forms_obj = MyForms()
    # 2.直接把空对象传递给html页面
    return render(request, 'index1.html',locals())
  • 步骤2:在html页面中通过对象点的方式得到表中字段对应的标签
  • 方式1(封装程度高 扩展性差)
{{ form_obj.as_p }}
{{ form_obj.as_table }}
{{ form_obj.as_ul }}
  • 方式2(封装程度低 扩展性好 编写困难)
 {{ form_obj.name.lable }}
 {{ form_obj.name }}
  • 方式3(推荐使用)
{% for form in form_obj %}
<p>{{ form.label }}{{ form }}</p>
{% endfor %}
5.forms组件之展示提示信息

views.py

from django import forms

class MyForms(forms.Form):
    name = forms.CharField(min_length=3, max_length=8, label='用户名',
                           error_messages={
                               'min_length': '用户名最少为3个字符',
                               'max_length': '用户名最大为8个字符',
                               'required': '用户名不能为空'
                           }
                           )
    pwd = forms.CharField(min_length=3, max_length=8, label='密码')
    confirm_pwd = forms.CharField(min_length=3, max_length=8, label='确认密码')
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                 'invalid': '邮箱格式不正确'
                             }

                             )

def index1(request):
    # 1.先产生一个空对象
    forms_obj = MyForms()
    if request.method == 'POST':
        # 3.校验数据
        forms_obj = MyForms(request.POST)  # request.POST 就是一个字典
        # 4.校验数据是否合法
        if forms_obj.is_valid():
            # 5.如果合法 操作数据库存储数据
            pass
        # 6.如果不合法  错误信息会展示到前端
    # 2.直接把空对象传递给html页面
    return render(request, 'index1.html',locals())

html页面

<form action="" method="post" novalidate>
    {% for form in forms_obj %}
        <p>
            {{ form.label }}{{ form }}
        <span style="color: red">{{ form.errors.0 }}</span>
        </p>
    {% endfor %}
    <input type="submit">
</form>
总结:
  • 1.想要取消前端页面的校验功能,直接在form标签中加入属性:novalidate
  • 2.get请求和post请求传给html页面对象的变量名必须一样(视图函数中的两个:forms_obj要一样)
  • 3.两个form_obj的作用:forms组件当你的数据不合法的时候情况下,会保存你上次的数据,让你基于上次的基础上进行修改数据,更加的便捷
  • 4.error_message可以自定义错误提示信息
  • 5.label可以自定义字段名称,即可以定义成汉字
  • 6.由于form.errors是一个列表,所以不许点0,拿到第一条数据

四:钩子函数

注意:钩子函数必须写在forms类中

1.分类:
  • 1.局部钩子:单个字段的校验,类似于第二道校验关卡
  • 2.全局钩子:多个字段的校验,类似于第二道校验关卡
2.局部钩子案例:校验name字段
    def clean_name(self):
        # 1.获取用户名
        name = self.cleaned_data.get('name')
        if 'h' in name:
            # 提示前端展示错误信息
            self.add_error('name', '名字中不能出现h')
            # 将钩子函数勾取的数据返回回去
        return name
3.全局钩子案例:校验pwd和comfirm_pwd
    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        confirm_pwd = self.cleaned_data.get('confirm_pwd')
        if not pwd == confirm_pwd:
            self.add_error('confirm_pwd', '两次密码不一致')
        return self.cleaned_data

五:forms组件重要参数

1.基本参数
参数作用
label字段注释
error_messages错误提示
required是否为空
initial默认值
validators正则校验
widget标签类型、标签属性

2.widget参数
  • input
widget=forms.widgets.TextInput(attrs={'class': 'form-control c1 c2', 'username': 'jason'})
  • password
pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )
  • radioSelect
gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
  • 单选select
hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )
  • 多选select
hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )
  • 单选checkbox
keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

  • 多选checkbox
hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

总结:

  • 1.多个属性值的话,直接用逗号隔开
3.validators正则校验
RegexValidator(r'^[0-9]+$','请输入数字')

六:modelform组件

1.modelform是forms组件的优化版本,使用更加简单

views.py

class MyModelForm(forms.ModelForm):
    class Meta:
        model = models.User
        fields = '__all__'
        exclude = ('age',)  # 把某个字段排除在外

    def clean_name(self):
        name = self.cleaned_data.get('name')
        res = models.User.objects.filter(name=name).first()
        if res:
            self.add_error('name', '用户名已存在')
        return name
    
def md(request):
    modelform_obj = MyModelForm()
    if request.method == 'POST':
        modelform_obj = MyModelForm(request.POST)
        if modelform_obj.is_valid():
            modelform_obj.save()  # 保存数据
    return render(request, 'md.html', locals())

html文件

<body>
<form action="" method="post" novalidate>
{% for model in modelform_obj %}
    <p>
        {{ model.label }}{{ model }}
    <span>{{ model.errors.0 }}</span>
    </p>
{% endfor %}
    <input type="submit">
</form>
</body>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值