• 开发工程师必备————【Day32】Django补充(七)


    今日内容概要

    • 批量操作数据
    • 自定义分页器(重在思路)
    • form组件
    • modelform组件

    批量操作数据

    • 浏览器访问一个django路由 立刻创建10万条数据并展示到前端页面
      create()、all()
    • 涉及到大批量数据的创建 直接使用create可能会造成数据库崩溃
      批量数据创建>>>:bulk_create()
      批量数据修改>>>:bulk_update()
    def index(request):
       # for i in range(100000):
       #     models.Book.objects.create(title=f'第{i}本书')
       book_list = []
       for i in range(100000):
           book_obj = models.Book(title=f'第{i}本书')
           book_list.append(book_obj)
       '''上述四行可以简写为一行>>>:列表生成式(列表表达式)'''
       models.Book.objects.bulk_create(book_list)  # 批量创建数据
       book_query = models.Book.objects.all()
       return render(request,'bookList.html',locals())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    批量数据展示

    当数据量比较大的时候 页面展示应该考虑分页
    1.QuerySet切片操作
    2.分页样式添加
    3.页码展示
    如何根据总数据和每页展示的数据得出总页码
    divmod()
    4.如何渲染出所有的页码标签
    前端模板语法不支持range 但是后端支持 我们可以在后端创建好html标签然后传递给html页面使用
    5.如何限制住展示的页面标签个数
    页码推荐使用奇数位(对称美) 利用当前页前后固定位数来限制
    6.首尾页码展示范围问题

    上述是分页器组件的推导流程 我们无需真正编写
    	django自带一个分页器组件 但是不太好用 我们自己也写了一个
    
    • 1
    • 2

    自定义分页器

    django自带的分页器组件。

    后端内容:
    
    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, 'bookList.html', locals())
    
    
    前端内容:
    
    {% for book_obj in page_query %}
    	<p class="text-center">{{ book_obj.title }}</p>
    {% endfor %}
    {{ page_obj.page_html|safe }}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    form组件

    1.前戏
    编写用户登录功能并且校验数据返回提示信息(form表单)

    	def ab_form(request):
       data_dict = {'username':'','password':''}
       if request.method == 'POST':
           username = request.POST.get('username')
           password = request.POST.get('password')
           if username == 'jason':
               data_dict['username'] = 'jason是你能随便用的吗'
           if password == '123':
               data_dict['password'] = '密码就设123???'
       return render(request,'ab_form.html',locals())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.form组件

    • 数据校验
      支持提前设置各种校验规则 之后自动校验
    • 渲染页面
      支持直接渲染获取用户数据的各种标签
    • 展示信息
      支持针对不同的校验失败展示不同的提示

    3.form类型创建
    举个栗子·:

    from django import forms
    
    class MyForm(forms.Form):
      name = forms.CharField(max_length=8, min_length=3)  # 用户名最长八个字符 最短三个字符
      age = forms.IntegerField(max_value=150, min_value=0)  # 年龄最小0岁 最大150岁
      email = forms.EmailField()  # 邮箱必须符合邮箱格式(至少有个@符号)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 数据校验功能

    (1)传递待校验的数据

    form_obj = views.MyForm({'name':'jason','age':18,'email':123})
    
    • 1

    (2)判断所有的数据是否符合校验

    form_obj.is_valid()
    
    • 1

    (3)获取符合校验规则的数据

    form_obj.cleaned_data
       	{'name': 'jason', 'age': 18}
    
    • 1
    • 2

    (4)查阅不符合校验规则的数据及错误原因

    form_obj.errors
       	{'email': ['Enter a valid email address.']}
    
    • 1
    • 2

    form类中编写的字段默认都是必填的 少传则肯定通不过校验 is_valid
    校验如果多传了一些字段 则不参与校验 全程忽略

    • 渲染标签功能

    (1)方式1(封装程度高 扩展性差)

    {{ form_obj.as_p }}
    		{{ form_obj.as_table }}
          {{ form_obj.as_ul }}
    
    • 1
    • 2
    • 3

    (2)方式2(封装程度低 扩展性好 编写困难)

    {{ form_obj.name.lable }}
         	{{ form_obj.name }}
    
    • 1
    • 2

    (3)方式3(推荐使用)

    {% for form in form_obj %}
           <p>{{ form.label }}{{ form }}</p>
       	{% endfor %}
    
    • 1
    • 2
    • 3

    类中以外的所有标签都不会自动渲染 需要自己编写

    • 展示提示信息
    form表单如何取消浏览器自动添加的数据校验功能:
    前端:
       	<form action="" method="post" novalidate>
      	{% for form in form_obj %}
           <p>
               {{ form.label }}{{ form }}
               <span style="color: red;">{{ form.errors.0 }}</span>
           </p>
       {% endfor %}
       <input type="submit" value="提交">
       
    后端:
       def func(request):
           form_obj = MyForm()
           if request.method == 'POST':
               form_obj = MyForm(request.POST)
               if form_obj.is_valid():
                   print(form_obj.cleaned_data)
           return render(request,'func.html',locals())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.重要的字段参数
    1.简单列举
    max_length、min_length
    max_value、min_value
    label 字段注释
    error_messages 错误提示
    required 是否为空
    widget 标签类型、标签属性
    initial 默认值
    validators 正则校验

    2.详细阐述几个

    • initial:input框里面的初始值:
    class LoginForm(forms.Form):
       username = forms.CharField(
           min_length=8,
           label="用户名",
           initial="张三"  # 设置默认值
       )
       pwd = forms.CharField(min_length=6, label="密码")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • error_messages:重写错误信息
    class LoginForm(forms.Form):
       username = forms.CharField(
           min_length=8,
           label="用户名",
           initial="张三",
           error_messages={
               "required": "不能为空",
               "invalid": "格式错误",
               "min_length": "用户名最短8位"
           }
       )
       pwd = forms.CharField(min_length=6, label="密码")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • password
    class LoginForm(forms.Form):
       ...
       pwd = forms.CharField(
           min_length=6,
           label="密码",
           widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • radioSelect:单radio值为字符串
    class LoginForm(forms.Form):
       username = forms.CharField(
           min_length=8,
           label="用户名",
           initial="张三",
           error_messages={
               "required": "不能为空",
               "invalid": "格式错误",
               "min_length": "用户名最短8位"
           }
       )
       pwd = forms.CharField(min_length=6, label="密码")
       gender = forms.fields.ChoiceField(
           choices=((1, "男"), (2, "女"), (3, "保密")),
           label="性别",
           initial=3,
           widget=forms.widgets.RadioSelect()
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 单选select:
    class LoginForm(forms.Form):
       ...
       hobby = forms.ChoiceField(
           choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
           label="爱好",
           initial=3,
           widget=forms.widgets.Select()
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 多选Select
    class LoginForm(forms.Form):
       ...
       hobby = forms.MultipleChoiceField(
           choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
           label="爱好",
           initial=[1, 3],
           widget=forms.widgets.SelectMultiple()
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 单选checkbox
    class LoginForm(forms.Form):
       ...
       keep = forms.ChoiceField(
           label="是否记住密码",
           initial="checked",
           widget=forms.widgets.CheckboxInput()
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 多选checkbox
    class LoginForm(forms.Form):
       ...
       hobby = forms.MultipleChoiceField(
           choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
           label="爱好",
           initial=[1, 3],
           widget=forms.widgets.CheckboxSelectMultiple()
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • RegexValidator验证器:添加正则要求
    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    from django.core.validators import RegexValidator
    
    class MyForm(Form):
       user = fields.CharField(
           validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), >RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
       )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5.钩子函数
    提供自定义的校验方式

    • 局部钩子:校验单个字段
    def clean_name(self):
               name = self.cleaned_data.get('name')
               res = models.User.objects.filter(name=name).first()
               if res:
                   return self.add_error('name','用户名已存在')
               return name
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 全局钩子:校验多个字段
    def clean(self):
               pwd = self.cleaned_data.get('pwd')
               confirm_pwd = self.cleaned_data.get('confirm_pwd')
               if not pwd == confirm_pwd:
                   return self.add_error('confirm_pwd','两次密码不一致')
               return self.cleaned_data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • form组件源码分析

    modelform组件

    1.简单介绍
    通常在Django项目中,我们编写的大部分都是与Django 的模型紧密映射的表单。 举个例子,你也许会有个Book 模型,并且你还想创建一个form表单用来添加和编辑书籍信息到这个模型中。 在这种情况下,在form表单中定义字段将是冗余的,因为我们已经在模型中定义了那些字段。
    基于这个原因,Django 提供一个辅助类来让我们可以从Django 的模型创建Form,这就是ModelForm。

    2.代码展示
    modelform是form的优化版本 使用更简单 功能更强大

    class MyModelForm(forms.ModelForm):
       class Meta:
           model = models.User
           fields = '__all__'
       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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.class Meta下常用参数:

    model = models.Book  # 对应的Model中的类
    fields = "__all__"  # 字段,如果是__all__,就是表示列出所有的字段
    exclude = None  # 排除的字段
    labels = None  # 提示信息
    help_texts = None  # 帮助提示信息
    widgets = None  # 自定义插件
    error_messages = None  # 自定义错误信息
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.ModelForm的验证

    • 与普通的Form表单验证类型类似,ModelForm表单的验证在调用is_valid() 或访问errors 属性时隐式调用。

    • 我们可以像使用Form类一样自定义局部钩子方法和全局钩子方法来实现自定义的校验规则。

    • 如果我们不重写具体字段并设置validators属性的化,ModelForm是按照模型中字段的validators来校验的。

    5.save()方法
    每个ModelForm还具有一个save()方法。 这个方法根据表单绑定的数据创建并保存数据库对象。 ModelForm的子类可以接受现有的模型实例作为关键字参数instance;如果提供此功能,则save()将更新该实例。 如果没有提供,save() 将创建模型的一个新实例:

    >>> from myapp.models import Book
    >> from myapp.forms import BookForm
    
    # 根据POST数据创建一个新的form对象
    >> form_obj = BookForm(request.POST)
    
    # 创建书籍对象
    >> new_ book = form_obj.save()
    
    # 基于一个书籍对象创建form对象
    >> edit_obj = Book.objects.get(id=1)
    # 使用POST提交的数据更新书籍对象
    >> form_obj = BookForm(request.POST, instance=edit_obj)
    >> form_obj.save()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    奥迪AUDI EDI INVOIC发票报文详解
    KMeans算法全面解析与应用案例
    SAS|画图
    【Rust日报】2022-06-27 Rust 中使用 wasm 来执行 OPA 策略
    【GPT‑4o】完整教程:LORA微调LLaMA3并结合RAG和Agent技术实现Text2SQL任务
    3.4 设置环境变量MAKEFILES
    mysql是如何查询数据的?
    JVM 垃圾回收详解
    白捡一个存储型XSS
    spark基本原理&UI界面解读
  • 原文地址:https://blog.csdn.net/DiligentGG/article/details/126773642