Django中ModelForm详解

modelform的常用配置#

from django import forms
from django.forms import widgets as wid #因为重名,所以起个别名


class ProjectForm(forms.ModelForm):
    class Meta:
        model = models.Project #对应的Model中的类
        # fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
        # fileds = ['project_status','project_name'] #列出的字段
        exclude = ['project_status']  # 排除哪些字段
        exclude = None          #排除的字段
        labels = None           #提示信息
        help_texts = None       #帮助提示信息
        widgets = None          #自定义插件
        error_messages = None   #自定义错误信息
        
#######################配置################################
        #labels,自定义在前端显示的名字
        labels = {
            "project_name": "项目名称",
            "project_detail": "项目描述",
        }
        #显示的错误信息
        error_messages = {
            "project_name": {"required": "不能为空"},
            "project_detail": {"required": "不能为空"}
        }
        #前端显示的input框
        widgets = {
            "project_name": wid.TextInput(attrs={"class": "form-control"}),  #还可以自定义属性
            "project_detail": wid.Textarea(attrs={"class": "form-control"})
        }

引用#

创建时引用#

html文件

<form action="" method="post" novalidate>
    {% csrf_token %}
    {% for foo in form %}
        <div class="form-group">
            <label for="">{{ foo.label }}</label>
            {{ foo }}
            <span style="color: red">{{ foo.errors.0 }}</span>
        </div>
    {% endfor %}
    <input type="submit" value="提交" class="btn btn-default">
</form>

views.py

def project_add(request):
    """ 新增项目记录 """
    if request.method == 'POST':
        form_obj = ProjectForm(request.POST)
        if form_obj.is_valid():
            form_obj.save()
            return redirect('/index/')
        else:
            return render(request, 'project_add.html', {'form': form_obj})
    else:
        form_obj = ProjectForm()
        return render(request, 'project_add.html', {"form": form_obj})

编辑时的用法#

html文件不变。
需要在使用modelform时使用instance传递数据,进行更新。
views.py

def project_update(request, pk):
    """ 更新项目 """
    model_obj = models.Project.objects.filter(pk=pk).first()
    if request.method == 'POST':
        form_obj = ProjectForm(request.POST, instance=model_obj)
        if form_obj.is_valid():
            form_obj.save()
            return redirect('/index/')
        else:
            return render(request, 'update_project.html', {'form': form_obj})
    else:
        form_obj = ProjectForm(instance=model_obj)
        return render(request, 'update_project.html', {"form": form_obj})

路由别忘了配置pk

from django.conf.urls import url
from django.contrib import admin
from app01 import views



urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index, name='index'),
    url(r'^project_update/(?P<pk>\d+)$', views.project_update, name='project_update'),
]

自定义标签#

适合一些特殊的标签,比如日期标签,下面是form设置。
法1

from django import forms
from django.forms import widgets as wid
from app01 import models

class ApiForm(forms.ModelForm):
    # 自定义标签
    api_start_time = forms.DateField(label="开始时间", widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
    api_stop_time = forms.DateField(label="结束时间",widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))

    class Meta:
        model = models.API
        fields = "__all__"
        # exclude = ['project_status']  # 排除哪些字段
        # labels = {
        #     "project_name": "项目名称",
        #     "project_detail": "项目描述",
        # }
        error_messages = {
            "api_title": {"required": "不能为空"},
            "api_desc": {"required": "不能为空"}
        }
        widgets = {
            "api_title": wid.TextInput(attrs={"class": "form-control"}),
            "api_desc": wid.Textarea(attrs={"class": "form-control"})
        }

        ##如:表中没有的字段想在前端显示? 如登录时的确认密码,表中没有这个字段,但前端是要显示的,可以这么写加上这个自定义字段
            confirm_password = forms.CharField(
              label='确认密码',
              widget=forms.PasswordInput(),  #这里和写wid.PasswordInput()一样,看源码导入的是同一个文件
              min_length=6,
              max_length=16,
              error_messages={
                  "min_length": "重复密码长度不能小于8位",
                  "max_length": "重复密码长度不能大于16位"
              },
          )

法2

from django.forms import ModelForm
from django import forms
from django.forms import widgets as wid
from app01 import models

class ApiForm(ModelForm):
    class Meta:
        model = models.API
        fields = "__all__"
    bootstrapClass_filter = ['api_start_time', 'api_stop_time']
    api_start_time= forms.DateField(label="开始时间",
                                     widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
    api_stop_time= forms.DateField(label="结束时间", widget=wid.DateInput(attrs={"class": "form-control", 'type': "date"}))
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            if name in self.bootstrapClass_filter:
                continue
            old_class = field.widget.attrs.get('class', "")
            field.widget.attrs['class'] = '{} form-control'.format(old_class)
            field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)

数据库:

class API(models.Model):
    """ 接口表 """
    api_title = models.CharField(max_length=32, verbose_name='接口名称')
    api_desc = models.CharField(max_length=128, verbose_name='接口描述')

    api_start_time = models.DateField(auto_now_add=True)
    api_stop_time = models.DateField(auto_now_add=True)
    def __str__(self):
        return self.api_title

    def xxoo(self):  # 自定义字段
        if self.case_set.count():
            a = "%s%% " % (self.case_set.filter(case_pass_status=1).count() / self.case_set.count() * 100)
            return a
        else:
            return 0

编辑数据:

如果不用ModelForm,编辑的时候得显示之前的数据吧,还得挨个取一遍值,如果ModelForm,只需要加一个instance=obj(obj是要修改的数据库的一条数据的对象)就可以得到同样的效果。

保存的时候要注意,一定要注意有这个对象(instance=obj),否则不知道更新哪一个数据。

代码示例:

img 使用ModelForm编辑数据

对于验证规则,很多浏览器都比较智能,会自动帮我们做一些验证,可以在form表单上加 novalidate 属性就可以不让浏览器为我们做验证

ModelForm还支持所有form的功能,比如钩子,所以我们就可以通过钩子来自定义验证规则

写法和forms的写法一样:

class AuthorForm(forms.ModelForm):
    class Meta:
        model = API
        fields = ('api_title')

    def clean_api_title(self):
        if ...
             return self.clean_data['api_title']  #如果校验正常,正常返回数据
       else:
             raise ValidationError(‘sdgsadga’)
        ...

作者: 听雨危楼

出处:https://www.cnblogs.com/Neeo/articles/10437793.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

仰望星空,脚踏实地

posted @ 2020-02-20 13:18  hanfe1  阅读(498)  评论(0编辑  收藏  举报