Python探索之ModelForm代码详解

这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把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方法介绍等,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

时间: 2017-10-23

编写Python的web框架中的Model的教程

有了ORM,我们就可以把Web App需要的3个表用Model表示出来: import time, uuid from transwarp.db import next_id from transwarp.orm import Model, StringField, BooleanField, FloatField, TextField class User(Model): __table__ = 'users' id = StringField(primary_key=True, defaul

在Python的web框架中配置app的教程

有了Web框架和ORM框架,我们就可以开始装配App了. 通常,一个Web App在运行时都需要读取配置文件,比如数据库的用户名.口令等,在不同的环境中运行时,Web App可以通过读取不同的配置文件来获得正确的配置. 由于Python本身语法简单,完全可以直接用Python源代码来实现配置,而不需要再解析一个单独的.properties或者.yaml等配置文件. 默认的配置文件应该完全符合本地开发环境,这样,无需任何设置,就可以立刻启动服务器. 我们把默认的配置文件命名为config_defa

在Python的web框架中编写创建日志的程序的教程

在Web开发中,后端代码写起来其实是相当容易的. 例如,我们编写一个REST API,用于创建一个Blog: @api @post('/api/blogs') def api_create_blog(): i = ctx.request.input(name='', summary='', content='') name = i.name.strip() summary = i.summary.strip() content = i.content.strip() if not name: r

在Python的web框架中中编写日志列表的教程

MVVM模式不但可用于Form表单,在复杂的管理页面中也能大显身手.例如,分页显示Blog的功能,我们先把后端代码写出来: 在apis.py中定义一个Page类用于存储分页信息: class Page(object): def __init__(self, item_count, page_index=1, page_size=10): self.item_count = item_count self.page_size = page_size self.page_count = item_c

在Python的Flask框架中实现单元测试的教程

 概要 在前面的章节里我们专注于在我们的小应用程序上一步步的添加功能上.到现在为止我们有了一个带有数据库的应用程序,可以注册用户,记录用户登陆退出日志以及查看修改配置文件. 在本节中,我们不为应用程序添加任何新功能,相反,我们要寻找一种方法来增加我们已写代码的稳定性,我们还将创建一个测试框架来帮助我们防止将来程序中出现的失败和回滚. 让我们来找bug 在上一章的结尾谈到,我故意在应用程序中引入一个bug.接下来让我描述一下它是什么样的bug,然后看看当我们的程序不按照我们意愿执行的时候,它在其中

Python之Web框架Django项目搭建全过程

Python之Web框架Django项目搭建全过程 IDE说明: Win7系统 Python:3.5 Django:1.10 Pymysql:0.7.10 Mysql:5.5 注:可通过pip freeze查看已安装库版本信息. Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站! Django 特点 强大的数据库功能 用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句. 自带的强大的后

Python:Scrapy框架中Item Pipeline组件使用详解

Item Pipeline简介 Item管道的主要责任是负责处理有蜘蛛从网页中抽取的Item,他的主要任务是清晰.验证和存储数据. 当页面被蜘蛛解析后,将被发送到Item管道,并经过几个特定的次序处理数据. 每个Item管道的组件都是有一个简单的方法组成的Python类. 他们获取了Item并执行他们的方法,同时他们还需要确定的是是否需要在Item管道中继续执行下一步或是直接丢弃掉不处理. Item管道通常执行的过程有 清理HTML数据 验证解析到的数据(检查Item是否包含必要的字段) 检查是

在laravel框架中使用model层的方法

创建model:php artisan make:model privilegeModel(名字随便写,可以不加Model) 控制器层加载model <?php namespace App\Http\Controllers\Admin; //注意命名空间 use App\Http\Controllers\Controller; use app\privilegeModel; function index(){ $model=new \App\PrivilegeModel(); //实例化mode

python开发实例之Python的Twisted框架中Deferred对象的详细用法与实例

Deferred对象在Twsited框架中用于处理回调,这对于依靠异步的Twisted来说十分重要,接下来我们就以实例解析Python的Twisted框架中Deferred对象的用法 Deferred对象结构 Deferred由一系列成对的回调链组成,每一对都包含一个用于处理成功的回调(callbacks)和一个用于处理错误的回调(errbacks).初始状态下,deffereds将由两个空回调链组成.在向其中添加回调时将总是成对添加.当异步处理中的结果返回时,Deferred将会启动并以添加时

如何在python开发工具PyCharm中搭建QtPy环境(教程详解)

在Python的开发工具PyCharm中安装QtPy5(版本5):打开"File"--"Settings"--"Project Interpreter",点击窗口中右侧点添加按钮,然后在弹出的窗口添加PyQt5模块包,单击Install Package按钮,如图所示: 安装好安装PyQt5后,需要用同样的方法安装pyqt5-tools,安装PyQt5后没有designer.exe就是因为没有安装pyqt5-tools.安装好PyQt5后,desi