Form组件------注册

form组件的主要功能如下:

  • 生成页面可用的HTML标签
  • 对用户提交的数据进行校验
  • 保留上次输入内容

forms.py         form组件一般单独放在一个py文件中,检验错误的信息放在 form_obj.errors

       例如:{ "pwd":["密码太长,"], "email":["格式不对,"] ,   }

def clean_user(self): 这个叫做局部钩子 也可以引入models.py 进行校验
from django.shortcuts import render, HttpResponse
from django.forms import Form, fields
from django import forms
from app01 import models

from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
引入
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",       # 设置默认值
        error_messages={                 # 重写错误信息。
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
                                },
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
                    RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
                        )

    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'},
        render_value=True, ) # 校验值回不回填到HTML页面中

    )

    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,    # 设置默认值
        widget=forms.widgets.RadioSelect  # 设置生成的HTML标签的type类型
    )


    def clean_username(self):
        username = self.cleaned_data.get("username")
        if "666" in username:
            raise ValidationError("光喊666是学不会!")
        else:
            return username

    def __init__(self, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        self.fields['hobby'].widget.choices = models.Hobby.objects.all().values_list('id', 'name')

    # def __init__(self, *args, **kwargs):   #  批量添加样式
    #     super(LoginForm, self).__init__(*args, **kwargs)
    #     for field in iter(self.fields):
    #         self.fields[field].widget.attrs.update({
    #             'class': 'form-control'
    #         })
            
定义一个Form类
class RegForm(forms.Form):

    user=forms.CharField(max_length=8,label="用户名",
                         widget=widgets.TextInput(attrs={"class":"form-control"})
                         )
    pwd=forms.CharField(min_length=4,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}))
    repeat_pwd=forms.CharField(min_length=4,label="确认密码",
                         widget=widgets.PasswordInput(attrs={"class": "form-control"}))
    email=forms.EmailField(label="邮箱",
                         widget=widgets.EmailInput(attrs={"class": "form-control"})
    )


    def clean_user(self):
        val=self.cleaned_data.get("user")
        # val=self.cleaned_data.get("pwd")

        ret=UserInfo.objects.filter(username=val)
        if not ret:
            return val
        else:
            raise ValidationError("该用户已存在")

    def clean(self):
        if self.cleaned_data.get("pwd")==self.cleaned_data.get("repeat_pwd"):
            return self.cleaned_data
        else:
            raise ValidationError("两次密码不一致!")
局部钩子 全局钩子

views.py

views.py     (from app import forms            from .models import UserInfo)
from app import forms 
from .models import UserInfo
引入
def register2(request):
    form_obj = RegisterForm()
    if request.method == "POST":
        form_obj = RegisterForm(request.POST)  # 把POST请求的数据传到RegisterForm
        if form_obj.is_valid():  # 执行校验规则
            # 校验通过
            # 从校验好的数据中取需要的字段值
            username = form_obj.cleaned_data.get("username")
            pwd = form_obj.cleaned_data.get("pwd")
            # 入库生成一条新纪录
            models.UserInfo.objects.create(usernama=username,pwd=pwd)
            return HttpResponse("注册成功")
    # 实例化一个RegisterForm对象
    return render(request, "register2.html", {"form_obj": form_obj})
def 函数逻辑

ps:   models.User.objects.create(**form_obj.cleaned_data) 

  cleaned_data里面没有csrftoken  k  v

html.html  (3种渲染方式)   ( 1、 {{ form_obj.as_p }}  会render初所有的,不建议使用)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>login</title>
  <style>
    .error {
      color: red;
    }
  </style>
</head>
<body>
<form action="/login2/" method="post" novalidate>
  {% csrf_token %}
  <p>
    {{ form_obj.username.label }}
    {{ form_obj.username }}
    <span class="error">{{ form_obj.username.errors.0 }}</span>
  </p>
  <p>
    {{ form_obj.pwd.label }}
    {{ form_obj.pwd }}
    <span class="error">{{ form_obj.pwd.errors.0 }}</span>
  </p>
  <p>
    <input type="submit">
    <span class="error">{{ error_msg }}</span>
  </p>
</form>
</body>
</html>
2、html(csrftoken)

 上边的如果字段很多会麻烦,此时可以使用for循环来生成,但是为了给每个标签添加样式可以使用  widget  =widgets...............   例如:widget  =widgets.PasswordInput.....密码变加密

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="" novalidate >
{#                form组件#}
                {% for field in form %}
                    <div class="form-group">
                        <label for="">{{ field.label }}</label>
                        {{ field }} <span class="error pull-right"></span>
                    </div>
                {% endfor %}
{#                    图片#}
                <div class="form-group">
                    <label for="avatar">头像<img class="avatar" src="/static/img/default.png" alt=""></label>
                    <input type="file" id="avatar">
                </div>
{#                上传#}
                <input type="button" class="btn btn-default reg_btn pull-right" value="提交"><span class="error"
                                                                                                 style="color: red;margin-left: 20px"></span>
            </form>
        </div>
    </div>
</div>

{% csrf_token %}
3、for循环(form=RegForm()) 

forms.py其他情况

select

class LoginForm(forms.Form):

    hobby = forms.fields.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select
    )
select单选
class LoginForm(forms.Form):

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

checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.fields.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput
    )
checkbox单选
class LoginForm(forms.Form):

    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple
    )
checkbox多选
gender=forms.ChoiceField(choices=((1,""),(2,""),(3,"其他")))
publish=forms.ChoiceField(choices=Publish.objects.all().values_list("pk","title"))
publish=forms.ModelChoiceField(queryset=Publish.objects.all())
authors=forms.ModelMultipleChoiceField(queryset=Author.objects.all())

爷类:chicefield                                                

父类:modelchoicefield   单选的select

子类:multiolechoicefield  多选的select

 

关于choice的注意事项:

在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

from django.forms import Form
from django.forms import widgets
from django.forms import fields

 
class MyForm(Form):
 
    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )
 
    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)
        #
        self.fields['user'].widget.choices = models.Classes.objects.all().values_list('id','caption')
choice实例化对象init

init还可以批量添加样式

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    ...

    def __init__(self, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })
init批量添加样式

 

posted @ 2018-04-27 19:44  nick560  阅读(237)  评论(0编辑  收藏  举报