• Form组件


    form组件功能

    1.数据校验功能

    1. # 提前准备好form类型
    2. from django import forms
    3. class MyForm(form.Form)
    4. name = forms.CharField(max_length=8,min_length=3)
    5. # 名字最长8个字符最短3个字符
    6. age = forms.IntegerField(max_value=150,min_value=0)
    7. # 年龄最大150 最低0
    8. email = forms.EmailField()
    9. # 邮箱必须符合邮箱格式@符号

    form组件支持提前设置各种校验规则之后自动校验:

            " role="presentation" style="position: relative;">  自定义一个继承form.Form的类

            " role="presentation" style="position: relative;">  实例化类,传入前端

            " role="presentation" style="position: relative;">  获得返回数据进行判断obj.is_valid()

            " role="presentation" style="position: relative;">  自定输入的错误类型返回给前端

    校验用户输入的信息是否符合表字段的参数  :

    1. # 1.传递待校验的数据
    2. form_obj = views.MyForm({'name':'haha','age':20,'email':'qqcom'})
    3. # 2.判断所有的数据是否符合校验
    4. form.obj.is_valid()
    5. # 3.获取符合校验规则的数据:{'name':'haha','age':20}
    6. form_obj.cleaned_data
    7. # 4.查看不符合校验规则的数据及错误原因:{'email': ['Enter a valid email address.']}
    8. form_obj.errors

     ps:form类中编写的字段默认都是必填的如果没有传入足够对应的数据则肯定通不过校验,但是如果多传入了字段则不影响校验多出来的字段不会参与校验直接忽略

    2.form组件渲染标签

            form组件支持直接渲染获取用户数据的各种标签,并有三种方式每一种方式都有自己的特点

    方式一:

    1. {{ form_obj.as_p }}
    2. {{ form_obj.as_table }}
    3. {{ form_obj.as_ul }}
    4. '''
    5. 优点:速度快 代码少
    6. 缺点:封装程度高 扩展性差
    7. '''

    方式二:

    1. {{ form_obj.name.lable }}
    2. {{ form_obj.name }}
    3. '''
    4. 优点:扩展性好
    5. 缺点:编写困难 封装程度低
    6. '''

    方式三:

    1. {% for form in form_obj %}
    2. {{ form.label }}{{ form }}

    3. {% endfor %}
    4. '''
    5. 推荐使用的方法 代码书写简单 并且可扩展性强
    6. 类以外的所有标签都不会自动渲染 需要自己编写
    7. '''

    3.form展示提示信息

            展示当校验不通过的时候提示的信息,但是浏览器会提前帮你走它自带的校验,前端校验又形同虚设所以我们得先取消浏览器的自动校验再设置form提示信息

    1. <for action="" method="post" novalidate>
    2. {% for form in form_obj %}
    3. <p>
    4. {{ form.label }}{{ form }}
    5. <span style = "color:red;">{{ form.errors.0 }}span>
    6. p>
    7. {% endfor %}
    8. <input type="submit" value="提交">
    1. # 在视图层
    2. def func(request):
    3. form_obj = MyForm()
    4. if request.method == 'POST':
    5. form_obj = MyForm(request.POST)
    6. if form_obj.is_valid():
    7. print(form_obj.cleaned_data)
    8. return render(request,'func.html',locals())

    4.form组件重要字段参数

            创建Form类时主要涉及到字段和插件,字段用于对用户请求数据的验证插件用于自动生成HTML

    1. CharField(Field)
    2. max_length=None 最大长度
    3. min_length=None 最小长度
    4. strip=True 去除用户输入空白
    5. IntegerField(Field)
    6. max_value=None 最大值
    7. min_value=None 最小值
    8. Field
    9. required 是否允许为空
    10. label 字段注释
    11. error_messages 错误信息{'':''}
    12. regex 自定义正则表达式
    13. initial 默认值

    钩子函数

            真正的数据校验应该是要结合数据库,我们通过利用钩子函数来校验用户注册登陆功能来理解钩子函数

    1. # 局部钩子:当注册用户名为haha是提示用户以注册
    2. def clean_name(self):
    3. name = self.cleaned_data.get('name')
    4. res = models.User.objects.filter(name=name).first()
    5. if res:
    6. return self.add_error('haha','用户以被注册')
    7. return name
    8. # 全局钩子:校验第一次密码与第二次密码是否一致
    9. # confirm_pwd为二次输入字段
    10. def clean(self):
    11. pwd = self.cleaned_data.get('pwd')
    12. confirm_pwd = self.cleaned_data.get('confirm_pwd')
    13. if not pwd == confirm_pwd:
    14. return self.add_error('confirm_pwd','两次密码不一致')
    15. return self.cleaned_data

    modelform组件

            通过名字就大致可以知道这个组件的多功能就是把model和form组合起来,更加优化了form使其用起来更简单功能更强大

    1. # 使用modelform组件
    2. class MyModelForm(forms.ModelForm):
    3. class Meta:
    4. model = models.User
    5. fields = '__all__'
    6. def clean_name(self):
    7. name = self.cleaned_data.get('name')
    8. res = models.User.objects.filter(name=name).first()
    9. if res:
    10. self.add_error('name','用户以注册')
    11. return name

    数据批量操作

            现在有一个需求当访问一个页面的时候立刻创建几万条数据并展示到这个页面上,如果这个需求直接用models加for循环来实现的时候还没有创建一半数据库就会奔溃并且加载速度很慢很慢

            针对大批量数据的创建与修改用普通的方式是不行的models给我们准备了特定的方式

    " role="presentation" style="position: relative;">  批量创建数据:bulk_create()

    " role="presentation" style="position: relative;">  批量修改数据:bulk_update()

    1. def index(request):
    2. book_list = []
    3. for i in range(100000):
    4. book_obj = models.Book(title=f'第{i}本书')
    5. book_list.append(book_obj)
    6. models.Book.objects.bulk_create(book_list)
    7. book_query = models.Book.objects.all()
    8. return render(request,'bookList.html',locals())

    自定义分页器

            当需要展示大量数据的时候如果同时一下子全部加载到页面上给人的观看感肯定不佳,同时也有卡死的现象,所以我们要用到分页指定一个页面展示几条这样就简介清楚

    " role="presentation" style="position: relative;"> 自定义分页器封装代码需要用的时候直接复制即可,但是其中原理最好能掌握

    1. class Pagination(object):
    2. def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
    3. """
    4. 封装分页相关数据
    5. :param current_page: 当前页
    6. :param all_count: 数据库中的数据总条数
    7. :param per_page_num: 每页显示的数据条数
    8. :param pager_count: 最多显示的页码个数
    9. """
    10. try:
    11. current_page = int(current_page)
    12. except Exception as e:
    13. current_page = 1
    14. if current_page < 1:
    15. current_page = 1
    16. self.current_page = current_page
    17. self.all_count = all_count
    18. self.per_page_num = per_page_num
    19. # 总页码
    20. all_pager, tmp = divmod(all_count, per_page_num)
    21. if tmp:
    22. all_pager += 1
    23. self.all_pager = all_pager
    24. self.pager_count = pager_count
    25. self.pager_count_half = int((pager_count - 1) / 2)
    26. @property
    27. def start(self):
    28. return (self.current_page - 1) * self.per_page_num
    29. @property
    30. def end(self):
    31. return self.current_page * self.per_page_num
    32. def page_html(self):
    33. # 如果总页码 < 11个:
    34. if self.all_pager <= self.pager_count:
    35. pager_start = 1
    36. pager_end = self.all_pager + 1
    37. # 总页码 > 11
    38. else:
    39. # 当前页如果<=页面上最多显示11/2个页码
    40. if self.current_page <= self.pager_count_half:
    41. pager_start = 1
    42. pager_end = self.pager_count + 1
    43. # 当前页大于5
    44. else:
    45. # 页码翻到最后
    46. if (self.current_page + self.pager_count_half) > self.all_pager:
    47. pager_end = self.all_pager + 1
    48. pager_start = self.all_pager - self.pager_count + 1
    49. else:
    50. pager_start = self.current_page - self.pager_count_half
    51. pager_end = self.current_page + self.pager_count_half + 1
    52. page_html_list = []
    53. # 添加前面的nav和ul标签
    54. page_html_list.append('''
      • ''')
      • first_page = '
      • 首页
      • ' % (1)
    55. page_html_list.append(first_page)
    56. if self.current_page <= 1:
    57. prev_page = '
    58. 上一页
    59. '
  • else:
  • prev_page = '
  • 上一页
  • ' % (self.current_page - 1,)
  • page_html_list.append(prev_page)
  • for i in range(pager_start, pager_end):
  • if i == self.current_page:
  • temp = '
  • %s
  • ' % (i, i,)
  • else:
  • temp = '
  • %s
  • ' % (i, i,)
  • page_html_list.append(temp)
  • if self.current_page >= self.all_pager:
  • next_page = '
  • 下一页
  • '
  • else:
  • next_page = '
  • 下一页
  • ' % (self.current_page + 1,)
  • page_html_list.append(next_page)
  • last_page = '
  • 尾页
  • ' % (self.all_pager,)
  • page_html_list.append(last_page)
  • # 尾部添加标签
  • page_html_list.append('''
  • ''')
  • return ''.join(page_html_list)
  • " role="presentation" style="position: relative;">  在后端中使用

    1. def get_book(request):
    2. book_list = models.Book.objects.all()
    3. current_page = request.GET.get("page",1)
    4. all_count = book_list.count()
    5. page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
    6. page_queryset = book_list[page_obj.start:page_obj.end]
    7. return render(request,'booklist.html',locals())

    " role="presentation" style="position: relative;">  在前端中使用

    1. <div class="container">
    2. <div class="row">
    3. <div class="col-md-8 col-md-offset-2">
    4. {% for book in page_queryset %}
    5. <p>{{ book.title }}p>
    6. {% endfor %}
    7. {{ page_obj.page_html|safe }}
    8. div>
    9. div>
    10. div>

    ps:有空时会补上分页具体的逻辑思想与用到的知识点分析

  • 相关阅读:
    上海控安SmartRocket系列产品推介(二):SmartRocket Modeler可视化建模开发工具
    阿里云RDS关系型数据库详细介绍_多版本数据库说明
    缓存穿透、缓存雪崩、缓存击穿问题的解决思路
    全国核辐射检测数据月度表
    Java反射
    探索科技地图:通向未来的科技之路
    python 终端输出带颜色的文字(ANSI颜色、背景颜色、字体效果等等)
    如何获取nod把子元素去掉,只需要n的父元素
    Vue3: el-table表格数据不显示
    带你初识微服务
  • 原文地址:https://blog.csdn.net/weixin_52596593/article/details/126767168