Python探索之ModelForm代码详解


Posted in Python onOctober 26, 2017

这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,对,你没猜错,相信自己的英语水平。

先来一个简单的例子来看一下这个东西怎么用:

比如我们的数据库中有这样一张学生表,字段有姓名,年龄,爱好,邮箱,电话,住址,注册时间等等一大堆信息,现在让你写一个创建学生的页面,你的后台应该怎么写呢?

首先我们会在前端一个一个罗列出这些字段,让用户去填写,然后我们从后天一个一个接收用户的输入,创建一个新的学生对象,保存

其实,重点不是这些,而是合法性验证,我们需要在前端判断用户输入是否合法,比如姓名必须在多少字符以内,电话号码必须是多少位的数字,邮箱必须是邮箱的格式这些

当然可以一点一点手动写限制,各种判断,这毫无问题,除了麻烦

我们现在有个更优雅(以后在Python相关的内容里,要多用“优雅”这个词,并且养成习惯)的方法:ModelForm

先来简单的,生硬的把它用上,再来加验证条件:

首先导入ModelForm

from django.forms import ModelForm

在视图函数中,定义一个类,比如就叫StudentList,这个类要继承ModelForm,在这个类中再写一个原类Meta(规定写法,并注意首字母是大写的)

在这个原类中,有以下属性(部分):

class StudentList(ModelForm):
  class Meta:
    model = models.Student #对应的Model中的类
    fields = "__all__"   #字段,如果是__all__,就是表示列出所有的字段
    exclude = None     #排除的字段
    labels = None      #提示信息
    help_texts = None    #帮助提示信息
    widgets = None     #自定义插件
    error_messages = None  #自定义错误信息
#error_messages用法:
    error_messages = {
      'name':{'required':"用户名不能为空",},
      'age':{'required':"年龄不能为空",},
    }
#widgets用法,比如把输入用户名的input框给为Textarea
#首先得导入模块
    from django.forms import widgets as wid #因为重名,所以起个别名
    widgets = {
      "name":wid.Textarea(attrs={"class":"c1"}) #还可以自定义属性
    }
#labels,自定义在前端显示的名字

labels= {
      "name":"用户名"
    }

然后在url对应的视图函数中实例化这个类,把这个对象传给前端

def student(request):

  if request.method == 'GET':
    student_list = StudentList()
    return render(request,'student.html',{'student_list':student_list})

然后前端只需要     {{ student_list.as_p }}   一下,所有的字段就都出来了,可以用as_p显示全部,也可以通过for循环这student_list,拿到的是一个个input框,现在我们就不用as_p,手动把这些input框搞出来,as_p拿到的页面太丑。

首先 for循环这个student_list,拿到student对象,直接在前端打印这个student,是个input框
student.label  ,拿到数据库中每个字段的verbose_name ,如果没有设置这个属性,拿到的默认就是字段名

还可以通过student.errors.0 拿到错误信息

有了这些,我们就可以通过bootstrap,自己拼出来想要的样式了

比如:

<body>
  <div class="container" >
    <h1>student</h1>
    <form method="POST" novalidate>
      {% csrf_token %}
{#      {{ student_list.as_p }}#}
      {% for student in student_list %}
        <div class="form-group col-md-6">
         {# 拿到数据字段的verbose_name,没有就默认显示字段名 #}
          <label class="col-md-3 control-label">{{ student.label }}</label>
          <div class="col-md-9" style="position: relative;">{{ student }}</div>
        </div>
      {% endfor %}
      <div class="col-md-2 col-md-offset-10">
        <input type="submit" value="提交" class="btn-primary">
      </div>
    </form>
  </div>
</body>

现在还缺一个input框的form-contral样式,可以考虑在后台的widget里面添加

比如这样:

from django.forms import widgets as wid #因为重名,所以起个别名
    widgets = {
      "name":wid.TextInput(attrs={'class':'form-control'}),
      "age":wid.NumberInput(attrs={'class':'form-control'}),
      "email":wid.EmailInput(attrs={'class':'form-control'})
    }

当然也可以在js中,找到所有的input框,加上这个样式,也行

保存数据的时候,不用挨个取数据了,只需要save一下

def student(request):

  if request.method == 'GET':
    student_list = StudentList()
    return render(request,'student.html',{'student_list':student_list})
  else:
    student_list = StudentList(request.POST)
    if student_list.is_valid():
      student_list.save()
    return redirect(request,'student_list.html',{'student_list':student_list})

编辑数据:

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

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

代码示例:

from django.shortcuts import render,HttpResponse,redirect
from django.forms import ModelForm
# Create your views here.
from app01 import models
def test(request):
  # model_form = models.Student
  model_form = models.Student.objects.all()
  return render(request,'test.html',{'model_form':model_form})

class StudentList(ModelForm):
  class Meta:
    model = models.Student #对应的Model中的类
    fields = "__all__"   #字段,如果是__all__,就是表示列出所有的字段
    exclude = None     #排除的字段
    labels = None      #提示信息
    help_texts = None    #帮助提示信息
    widgets = None     #自定义插件
    error_messages = None  #自定义错误信息
#error_messages用法:
    error_messages = {
      'name':{'required':"用户名不能为空",},
      'age':{'required':"年龄不能为空",},
    }
#widgets用法,比如把输入用户名的input框给为Textarea
#首先得导入模块
    from django.forms import widgets as wid #因为重名,所以起个别名
    widgets = {
      "name":wid.Textarea
    }
#labels,自定义在前端显示的名字
    labels= {
      "name":"用户名"
    }
def student(request):
  if request.method == 'GET':
    student_list = StudentList()
    return render(request,'student.html',{'student_list':student_list})
  else:
    student_list = StudentList(request.POST)
    if student_list.is_valid():
      student_list.save()
    return render(request,'student.html',{'student_list':student_list})
def student_edit(request,pk):
  obj = models.Student.objects.filter(pk=pk).first()
  if not obj:
    return redirect('test')
  if request.method == "GET":
    student_list = StudentList(instance=obj)
    return render(request,'student_edit.html',{'student_list':student_list})
  else:
    student_list = StudentList(request.POST,instance=obj)
    if student_list.is_valid():
      student_list.save()
    return render(request,'student_edit.html',{'student_list':student_list})

总结

以上就是本文关于Python探索之ModelForm代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:python编程羊车门问题代码示例、python中requests使用代理proxies方法介绍等,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
50行代码实现贪吃蛇(具体思路及代码)
Apr 27 Python
深入浅析python中的多进程、多线程、协程
Jun 22 Python
Python实现字典按照value进行排序的方法分析
Dec 23 Python
解决Python内层for循环如何break出外层的循环的问题
Jun 24 Python
pytorch 可视化feature map的示例代码
Aug 20 Python
Python如何使用argparse模块处理命令行参数
Dec 11 Python
Python标准库shutil模块使用方法解析
Mar 10 Python
Pytorch高阶OP操作where,gather原理
Apr 30 Python
如何使用PyCharm引入需要使用的包的方法
Sep 22 Python
Python threading模块condition原理及运行流程详解
Oct 05 Python
python中if和elif的区别介绍
Nov 07 Python
如何使用python包中的sched事件调度器
Apr 30 Python
启动targetcli时遇到错误解决办法
Oct 26 #Python
Mac中Python 3环境下安装scrapy的方法教程
Oct 26 #Python
python实现分页效果
Oct 25 #Python
python+pyqt实现12306图片验证效果
Oct 25 #Python
python编程羊车门问题代码示例
Oct 25 #Python
python中requests使用代理proxies方法介绍
Oct 25 #Python
python中requests爬去网页内容出现乱码问题解决方法介绍
Oct 25 #Python
You might like
Php中用PDO查询Mysql来避免SQL注入风险的方法
2013/04/25 PHP
关于尾递归的使用详解
2013/05/02 PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
2018/10/15 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
jquery 学习之二 属性(类)
2010/11/25 Javascript
获取元素距离浏览器周边的位置的方法getBoundingClientRect
2013/04/17 Javascript
JavaScript设置body高度为浏览器高度的方法
2015/02/09 Javascript
js网页滚动条滚动事件实例分析
2015/05/05 Javascript
JS原型、原型链深入理解
2016/02/27 Javascript
Javascript基础学习笔记(菜鸟必看篇)
2016/07/22 Javascript
Vue 2.0学习笔记之使用$refs访问Vue中的DOM
2017/12/19 Javascript
js实现微信/QQ直接跳转到支付宝APP打开口令领红包功能
2018/01/09 Javascript
360doc网站不登录就无法复制内容的解决方法
2018/01/27 Javascript
浅谈关于iview表单验证的问题
2018/09/29 Javascript
详解如何在vscode里面调试js和node.js的方法步骤
2018/12/24 Javascript
vue+Element中table表格实现可编辑(select下拉框)
2020/05/21 Javascript
详解node.js 事件循环
2020/07/22 Javascript
Python PIL读取的图像发生自动旋转的实现方法
2019/07/05 Python
Python socket模块ftp传输文件过程解析
2019/11/05 Python
利用python实现冒泡排序算法实例代码
2019/12/01 Python
Python远程开发环境部署与调试过程图解
2019/12/09 Python
Eclipse配置python默认头过程图解
2020/04/26 Python
python查看矩阵的行列号以及维数方式
2020/05/22 Python
python中的错误如何查看
2020/07/08 Python
浅析CSS3 中的 transition,transform,translate之间区别和作用
2020/03/26 HTML / CSS
检测浏览器对HTML5和CSS3支持度的方法
2015/06/25 HTML / CSS
Shopee马来西亚:随拍即卖,最佳行动电商拍卖平台
2017/06/05 全球购物
Desigual德国官网:在线购买原创服装
2018/03/27 全球购物
澳洲健康食品网上商店:Aussie Health Products
2018/06/15 全球购物
英国领先的鞋类零售商和顶级品牌的官方零售商:Wynsors
2020/02/17 全球购物
一套PHP的笔试题
2013/05/31 面试题
什么是重载?CTS、CLS和CLR分别做何解释
2012/05/06 面试题
一些Solaris面试题
2015/12/22 面试题
劳动之星获奖感言
2014/02/01 职场文书
《放飞蜻蜓》教学反思
2014/04/27 职场文书
一文搞懂Redis中String数据类型
2022/04/03 Redis