form组件和modelform

form组件

先来个注册页面项目

models.py

# models.py
from django.db import models


class UserInfo(models.Model):
    id = models.AutoField(primary_key=True)
    user = models.CharField(max_length=32, unique=True, null=False)
    pwd = models.CharField(max_length=10)
    email = models.EmailField(default="aki@gmail.com")
    mobile = models.CharField(max_length=11)

    class Meta:
        unique_together = ('user',)

    def __str__(self):
        return self.user

 

views.py

含有自定义校验字段

# views.py
from django.shortcuts import render, HttpResponse
from app0001 import models
from django import forms
from django.forms import widgets, fields
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError


class RegForm(forms.Form):
    user = forms.CharField(max_length=8, min_length=2, label="用户名",
                           error_messages={
                               "min_length": "用户名不少于2位",
                               "required": "该字段不能为空",
                           },
                           widget=widgets.TextInput(attrs={"class": "form-control"}))
    pwd = forms.CharField(max_length=10, min_length=4, label="密码",
                          error_messages={
                              "min_length": "密码不少于4位",
                              "required": "该字段不能为空",
                          },
                          widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True)
                          # render_value  刷新页面密码不丢失, 只有密码有这个属性
                          )

    re_pwd = forms.CharField(max_length=10, min_length=4, label="确认密码",
                             error_messages={
                                 "min_length": "密码不少于4位",
                                 "max_length": "密码太长",
                                 "required": "该字段不能为空",
                             },
                             widget=widgets.PasswordInput(attrs={"class": "form-control"}, render_value=True)
                             )

    email = forms.EmailField(label="邮箱",
                             widget=widgets.EmailInput(attrs={"class": "form-control"}),
                             disabled=True,
                             # 不可编辑
                             initial='jjssw@qq.com',
                             # 指定默认值
                             error_messages={
                                 "required": "该字段不为空",
                                 "invalid": "格式错误",
                             })

    mobile = forms.CharField(label="手机号",
                             widget=widgets.TextInput(attrs={"class": "form-control"}),
                             validators=[
                                 RegexValidator(r'^[0-9]+$', '输入数字'),
                                 RegexValidator(r'^1[3-9][0-9]{9}$', '格式错误')
                             ],
                             error_messages={
                                 "required": "该字段不为空",
                             })

    def clean_user(self):
        value = self.cleaned_data.get('user')
        a = ["敏感", "词汇"]
        for i in a:
            if i in value:
                raise ValidationError('形式所迫')
        is_exist = models.UserInfo.objects.filter(user=value)
        if is_exist:
            raise ValidationError('用户名重了, 老弟')
        return value

    def clean(self):
        # 注释掉的是检查用户名名是否存在, 而且局部钩子先生效, 也就是说先走局部钩子
        # user = self.cleaned_data.get('user')
        # is_exist = models.UserInfo.objects.filter(user=user)
        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('')
        # if is_exist:
        #     self.add_error('user', ValidationError("用户名重复"))
        #     raise ValidationError('')
        return self.cleaned_data


def form(request):
    form_obj = RegForm()
    if request.method == "POST":
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():
            print(form_obj.cleaned_data)
            del form_obj.cleaned_data["re_pwd"]
            models.UserInfo.objects.create(**form_obj.cleaned_data)
            return HttpResponse('ojbk')
    return render(request, "reg.html", {"form_obj": form_obj}, )

reg.html

// reg.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册表单</title>
</head>
<body>
<link rel="stylesheet" href="/static/bootstrap.min.css">
<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-4">
            <form action="/form/" method="post" novalidate autocomplete="off">
            {% csrf_token %}
                <div class="form_group {% if form_obj.user.errors.0 %} has-error{% endif %}">
                    {{ form_obj.user.label }}
                    {{ form_obj.user }}
                    <span class="help-block">{{ form_obj.user.errors.0 }}</span>

                </div>
                <div class="form_group {% if form_obj.pwd.errors.0 %} has-error {% endif %}">
                    {{ form_obj.pwd.label }}
                    {{ form_obj.pwd }}
                    <span class="help-block">{{ form_obj.pwd.errors.0}}</span>
                </div>
                <div class="form_group {% if form_obj.re_pwd.errors.0 %} has-error {% endif %}">
                    {{ form_obj.re_pwd.label }}
                    {{ form_obj.re_pwd }}
                    <span class="help-block">{{ form_obj.re_pwd.errors.0}}</span>
                </div>
                <div class="form_group {% if form_obj.email.errors.0 %} has-error {% endif %}">
                    {{ form_obj.email.label }}
                    {{ form_obj.email }}
                    <span class="help-block">{{ form_obj.email.errors.0}}</span>
                </div>
                 <div class="form_group {% if form_obj.mobile.errors.0 %} has-error {% endif %}">
                    {{ form_obj.mobile.label }}
                    {{ form_obj.mobile }}
                    <span class="help-block">{{ form_obj.mobile.errors.0}}</span>
                </div>
                <button type="submit">提交啊</button>
            </form>
        </div>
    </div>
</div>
<script src="/static/jquery-3.3.1.min.js"></script>
<script src="/static/bootstrap.min.js"></script>
</body>
</html>

渲染标签的几种方式

1) {{ form_obj.pwd.label }}  {{ form_obj.pwd }}

2)    {% for fields in form %}

             {{ field.label }}

             {{ field }}

        {% endfor %}

 

表单输出选项

  • {{ form.as_table }}:以表格形式加载表单元素  要加<table> {{ form.as_table }}</table>

  • {{ form.as_p }}:以段落形式加载表单元素

  • {{ form.as_ul }:以列表形式加载表单元素       要加<ul> {{ form.as_ul }}</ul>

表单相关的属性

  • {{ field.label }}:字段对应的<lable>标签的文字,例如“发件人”。

  • {{ field.label_tag }}:字段对应的<lable>标签。

  • {{ field.id_for_label }}:字段的“id”属性值。

  • {{ field.value }}:字段的值,例如标题的内容。

  • {{ field.html_name }}:字段对应的HTML标签“name”属性的值。

  • {{ field.help_text }}:字段的帮助文本。

  • {{ field.errors }}:包含任何字段验证错误的全部信息,可以通过“{% for error in field.errors %}”的方式遍历。

  • {{ field.is_hidden }}:字段是否隐藏字段,获取到的是布尔值。

  • {{ field.field }}:字段对象,可以通过它访问字段的属性,例如“{{ field.field.max_length }}”,“{{ field.field.required}}”。

 

 

静态字段(只有choice)

实时刷新, 不用重启django

1)重写__init__

from django import forms
from django.forms import widgets, fields
 
 
class A(forms.Form):
    price = fields.IntegerField()
    user_id = fields.IntegerField(
        widget=widgets.Select()
        # widget=widgets.Select(choices=models.Userinfo.objects.valuse_list('id', 'username'))
        # 实际要查上面的, 但是每次最先加载__init__, 加载init时就已经查找完了, 在这里如果再查找就重复了
    )
 
    def __init__(self, *args, **kwargs):
        super(A, self).__init__(*args, **kwargs)
        self.fields['user_id'].widget.choices = models.Userinfo.objects.valuse_list('id', 'username')

2)自动更新(ModelChoiceField)

在views.py中的form写法

class UserForm(forms.Form):
    username = ModelChoiceField(queryset=models.UserInfo.objects.all(), to_field_name='指定在数据库的叫什么')

但是也带来了前端显示不正常的问题

所以要在models中加

from django.db import models
 
 
class UserInfo(models.Model):
    username = models.CharField(max_length=33)
    
    def __str__(self):
        return self.username

form表单字段

from django import forms

from django.forms import widgets, fields

 

下拉框

单选select(initial默认选2)

user = fields.CharField(initial=2, widget=widgets.Select(choices=((1, 'x'), (2, 'a'))))
# user = fields.ChoiceField(choices=(), widget=widgets.Select())

多选select(attrs 给它加属性)

user = fields.MultipleChoiceField(choices=(), widget=widgets.SelectMultiple(attrs={'class': ''}))

 

单选框

user = fields.CharField(widget=widgets.RadioSelect(choices=()))
 
# user = fields.ChoiceField(choices=(), widget=widgets.RadioSelect)

 

复选框

单选

user = fields.ChoiceField(widget=widgets.CheckboxInput(attrs=()))

多选

user = fields.MultipleChoiceField(choices=(), widget=widgets.CheckboxSelectMultiple)

 

modelform

         class Meta:
            model,                           # 对应Model的
            fields=None,                     # 字段
            exclude=None,                    # 排除字段
            labels=None,                     # 提示信息
            help_texts=None,                 # 帮助提示信息
            widgets=None,                    # 自定义插件
            error_messages=None,             # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
            field_classes=None               # 自定义字段类 (也可以自定义字段)
            localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
model 和 Forms对应关系
modelForms
一对多forms.ModelChoiceField
多对多forms.ModelMaltipleChiceField

一对多的type:     <class 'django.forms.model.ModelChoiceField'>

 多对多的type:    <class 'django.forms.model.ModelMultiChoiceField'>

 

判断forn或modelform渲染的字段是不是一对多或多对多

from django.forms.model import ModelChiceField
form = ModelFormDemo()
for bfield in form:
    if istance(bfield.field, ModelChoiceField):
           # 是否一对多字段
        bfield.is_pop = True
          # 对象可以 .xx给它加属性

'''
所以前端可以这样

{% if field.is_pop %}
可以判断是否是一对多, 多对多

'''


print(bfield.field.queryset.model)
# 打印 <class 'app01.model.Publish'>


print(bfield.field.queryset.model._meta.model_name)
# Publish
    

 

form组件的limit_chocie_to={}  

作用于一对多和多对多 

teacher = models.ManyToManyField(..., limit_choice_to = {"depart__in": [1002, 1005]})

相应的也可以在forms中

data = UserInfo.objects.filter(depart__in=[1002, 1005]) .values(''pk", "title")

tracher = forms.ModelMutichoice(choices=data)

实例

views.py

modelform 同样可以用全局的和局部的钩子

from django.forms import ModelForm


class UserForm(ModelForm):
    # 重写user字段, 并覆盖
    # user = fields.ChoiceField(choices=((1, '男'), (2, '女')))

    class Meta:
        model = models.UserInfo
        fields = "__all__"
        # fields = ['xx', 'xx']     指定那个字段
        # exclude = ['xx', 'xx']    排除那个字段
        error_messages = {
            'email': {
                'invalid': '格式不对'
            }
        }

        labels = {
            # 给每个标签指定别名
            'user': '用户名啊',
            'pwd': '密码呀'
        }
        widgets = {
            # 渲染标签
            # 'user': widgets.Textarea(attrs={'class': 'c1'})
        }

    def clean_user(self):
        value = self.cleaned_data.get('user')
        a = ["敏感", "词汇"]
        for i in a:
            if i in value:
                raise ValidationError('形式所迫')
        is_exist = models.UserInfo.objects.filter(user=value)
        if is_exist:
            raise ValidationError('用户名重了, 老弟')
        return value


def index(request):
    if request.method == "POST":
        myForm = UserForm(request.POST)
        if myForm.is_valid():
            myForm.save()
            return HttpResponse('ok')
        # 没写else 没显示错误信息
        else:
            return render(request, "test.html", {"form": myForm})
    myForm = UserForm()
    return render(request, "test.html", {"form": myForm})

models

from django.db import models


class UserInfo(models.Model):
    # 每个字段指定verbose_name, 则modelform显示指定内容, 也可以在modelform里指定
    id = models.AutoField(primary_key=True, )
    user = models.CharField(max_length=32, unique=True, null=False, )
    pwd = models.CharField(max_length=10, )
    email = models.EmailField(default="aki@gmail.com", verbose_name='邮件')
    mobile = models.CharField(max_length=11, verbose_name='手机')

    class Meta:
        verbose_name = "项目名称"
        unique_together = ('user',)

    def __str__(self):
        return self.user

tses.html

<form action="/index/" method="post" novalidate>
    {% csrf_token %}
    {% for field in form %}
        <div>
        {{ field.label }}
        {{ field }}
        <span>{{ field.errors.0 }}</span>
        </div>


    {% endfor %}
    <label for="i1">提交按钮</label>
    <input type="submit" value="提交" id="i1">
</form>

下面是modelform编辑的demo

def edit(request, nid):
    edi_obj = UserForm.object.filter(pk=nid).first()
    if request == "POST":
        form = UserForm(request.POST, instance=nid)
        # instance 说明修改哪一个, 不传就成了添加
        if form.is_valid():
            form.save()
            return HttpResponse("ok")
        form = UserForm(instance=nid)
        # get 请求时input 有默认值
        return render(request, 'xxx.html', locals())

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值