Day 55 form组件

1. form组件创建页面的四种使用方式:

1.1方式一;手动写

<!-- novalidate 告诉浏览器不要去给我校验-->
<!-- 方式一    : 手写HTMl-->
<form action="" method="POST" novalidate>
{% csrf_token %}
<!-- novalidate 告诉浏览器不要去给我校验-->
<!-- 方式一 : 手写HTMl-->
<!-- <p>用户名:<input type="text" name="username"></p>-->
<!-- <p>年龄:<input type="text" name="age"></p>-->
<!-- <p>工资: <input type="text" name="salary"></p>-->
<!-- <input type="submit">-->
 

 此时视图函数中的代码:

1.2 利用自定义的form组件类在视图函数创建一个对象填充到前端页面当中去

视图函数中的代码:

def add_emp(request):
    if request.method == "GET":
        form = EmpForm()
        return render(request, "add_emp.html", {"form": form})

前端add_emp.html的代码:

方式二:

 <form action="" method="POST" novalidate>
                {% csrf_token %}
<!--    方式二:form自带的as_p-->
<!--        {{ form.as_p }}-->
<!--<input type="submit">

方式三:

<!--    方式3 -->

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <h3>新增员工</h3>
            <form action="" method="POST" novalidate>
                {% csrf_token %}
                <div class="form-group {% if form.name.errors.0 %}has-error{% endif %}">

                    <label for="id_{{ form.name.name }}">{{ form.name.label }}</label>
                    {{ form.name }} <span class="help-block">{{ form.name.errors.0 }}</span>
                </div>
                <div class="form-group {% if form.age.errors.0 %}has-error{% endif %} ">
                    <label for="id_{{ form.age.name }}">{{ form.age.label }}</label>
                    {{ form.age }} <span class="help-block">{{ form.age.errors.0 }}</span>
                </div>
                <div class="form-group {% if form.salary.errors.0 %}has-error{% endif %}">
                    <label for="id_salary">工资</label>
                    {{ form.salary }} <span class="help-block">{{ form.salary.errors.0 }}</span>
                </div>
                <div class="form-group {% if form.r_salary.errors.0 %}has-error{% endif %}">
                    <label for="id_r_salary">{{ form.r_salary.label }}</label>
                    {{ form.r_salary }} <span class="help-block">{{ form.r_salary.errors.0 }} {{ clean_errors.0 }}</span>
                </div>
                <input type="submit">

            </form>
        </div>
    </div>
</div>
</body>
</html>

视图函数中的代码:

from django.shortcuts import render, HttpResponse
from django.shortcuts import render
from app01.My_Forms import EmpForm
from app01 import models
# Create your views here.


def add_emp(request):
    if request.method == "GET":
        form = EmpForm()
        return render(request, "add_emp.html", {"form": form})

    else:

        form = EmpForm(request.POST)
        if form.is_valid():  # 进行数据校验
            # 校验成功
            data = form.cleaned_data  # 校验成功的值,会放在cleaned_data里。
            print(data)
            data.pop('r_salary')
            print(data)
            # {'name': 'alex', 'age': 28, 'salary': Decimal('11')}
            models.Emp.objects.create(**data)
            return HttpResponse("ok")
        else:
            print(form.errors) # 打印错误的信息
            # print(111)
            # return HttpResponse("aaa")
            clean_errors = form.errors.get("__all__")
            return render(request, "add_emp.html", {"form": form, "clean_errors": clean_errors})
小结:在有全局钩子的时候,出错的时候需要将全局钩子出错的clean_errors 传入到后端中填充页面,就行显示。一般的错误传入form对象即可。

2.常用字段定义

#          Django Form组件的使用
from django import forms
from django.forms import widgets
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError


class RegForm(forms.Form):
    name = forms.CharField(
        # 校验规则相关
        max_length=16,
        label="用户名",
        error_messages={
            "required": "该字段不能为空",
        },
        # widget控制的是生成html代码相关的
        widget=widgets.TextInput(attrs={"class": "form-control"})
    )
    pwd = forms.CharField(
        label="密码",
        min_length=6,
        max_length=10,
        widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),
        error_messages={
            "min_length": "密码不能少于6位!",
            "max_length": "密码最长10位!",
            "required": "该字段不能为空",
        }
    )
    re_pwd = forms.CharField(
        label="确认密码",
        min_length=6,
        max_length=10,
        widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True),
        error_messages={
            "min_length": "密码不能少于6位!",
            "max_length": "密码最长10位!",
            "required": "该字段不能为空",
        }
    )

    email = forms.EmailField(
        label="邮箱",

        widget=widgets.EmailInput(attrs={"class": "form-control"}),
        error_messages={
            "required": "该字段不能为空",
        }
    )
    mobile = forms.CharField(
        label="手机",
        # 自己定制校验规则
        validators=[
            RegexValidator(r'^[0-9]+$', '手机号必须是数字'),
            RegexValidator(r'^1[3-9][0-9]{9}$', '手机格式有误')
        ],
        widget=widgets.TextInput(attrs={"class": "form-control"}),
        error_messages={
            "required": "该字段不能为空",
        }
    )

    city = forms.ChoiceField(
        choices=models.City.objects.all().values_list("id", "name"),
        label="城市",
        initial=1,
        widget=forms.widgets.Select
    )

    # 重写父类的init方法
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")


    def clean_name(self):
        value = self.cleaned_data.get("name")
        if "金 瓶 梅" in value:
            raise ValidationError("不符合社会主义核心价值观!")
        return value

    # 重写父类的clean方法
    def clean(self):
        # 此时 通过检验的字段的数据都保存在 self.cleaned_data
        pwd = self.cleaned_data.get("pwd")
        re_pwd = self.cleaned_data.get("re_pwd")
        if pwd != re_pwd:
            self.add_error("re_pwd", ValidationError("两次密码不一致"))
            raise ValidationError("两次密码不一致")
        return self.cleaned_data
    # gender = forms.ChoiceField(
    #     choices=((1, "男"), (2, "女"), (3, "保密")),
    #     label="性别",
    #     initial=1,
    #     widget=forms.widgets.RadioSelect
    # )
    # hobby = forms.ChoiceField(
    #     choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    #     label="爱好",
    #     initial=3,
    #     widget=forms.widgets.Select
    # )
    # hobby2 = forms.MultipleChoiceField(
    #     choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    #     label="爱好",
    #     initial=[1, 3],
    #     widget=forms.widgets.SelectMultiple()
    # )
    #
    # keep = forms.ChoiceField(
    #     label="是否记住密码",
    #     initial="checked",
    #     widget=forms.widgets.CheckboxInput
    # )
    # hobby3 = forms.MultipleChoiceField(
    #     choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    #     label="爱好",
    #     initial=[1, 3],
    #
    #     widget=forms.widgets.CheckboxSelectMultiple(attrs={"class": "c1"})
    # )

其中如果在前端的页面中需要去选择下拉列表的时候:

  city = forms.ChoiceField(
        choices=models.City.objects.all().values_list("id", "name"),
        label="城市",
        initial=1,
        widget=forms.widgets.Select
    )

    # 重写父类的init方法
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")

即是查询其他的数据库就行一个显示,注意的是需要重写父类的方法,不然需要重启服务器。

参考:李文综老师博客:https://www.cnblogs.com/liwenzhou/p/8747872.html

猜你喜欢

转载自www.cnblogs.com/longerandergou/p/11235389.html
55