python自定义表单_Python自动化开发学习24-Django上(ModelForm)

使用ModelForm创建

接下来要使用的表结构如下:

# models.py 文件

class UserType(models.Model):

caption = models.CharField(max_length=32)

class UserInfo(models.Model):

username = models.CharField(max_length=32)

email = models.EmailField()

user_type = models.ForeignKey(to='UserType', on_delete=models.CASCADE)

表结构写好之后,生成数据库:

···

python manage.py makemigrations

python manage.py migrate

···

ModelForm

上节就说过,ModelForm很简单,所以就下面几行,没太多内容:

# forms.py 文件

class UserInfo(forms.ModelForm):

class Meta:

model = models.UserInfo

fields = '__all__'

处理函数

# views.py 文件

def user_info(request):

if request.method == 'GET':

obj = forms.UserInfo()

return render(request, 'user_info.html', {'obj': obj})

elif request.method == 'POST':

obj = forms.UserInfo(request.POST)

return render(request, 'user_info.html', {'obj': obj})

HTML

最后再页面上显示出来

{% csrf_token %}

{{ obj.as_p }}

最后打开页面查看一下,也是可以自动生成html标签的,并且效果上和之前用的Form基本没什么区别。

自定义label

上面在页面中显示的名称是默认的变量名,如果要显示中文,需要在models里定一个变量 verbose_name。

之前在 Python自动化开发学习19-Django 里讲过models的参数。verbose_name :Admin中显示的字段名称,默认显示为变量名。我们用ModelForm也是一样的,因为Admin里用的就是ModelForm。

修改的代码并行下面要将的内容一起了。

显示选项的内容

因为现在usertype表里是空的,所以select下拉列表里没有其他选项。添加几条数据后,页面上会有相应的选项了,但是显示的内容是对象。为了让他显示内容,还要在类里定一个 __str__ 方法。

连同上面显示中文标签一起,修改为下面的样子:

# modelspy 文件

class UserType(models.Model):

caption = models.CharField(max_length=32)

def __str__(self):

return self.caption

class UserInfo(models.Model):

username = models.CharField(verbose_name="用户名", max_length=32)

email = models.EmailField(verbose_name="电子邮件")

user_type = models.ForeignKey(verbose_name="用户类型", to='UserType', on_delete=models.CASCADE)

定制页面显示的字段

上面的ModelForm里面的元类的fields变量,设置的是显示所有的字段,也可以传入一个列表,只显示要求的那些字段。或者是使用exclude,表示排除哪些字段:

# fields = '__all__'

# fields = ['username', 'user_type']

exclude = ['email']

ModelForm 中 Form 的功能

先了解一下ModelForm和Form的关系。

之前学习使用的Form,继承的是BaseForm。我这里用的ModelForm,父类是BaseModelForm,再网上找继承的还是BaseForm。

之前学习Form的时候,讲到Form的2个功能,验证和生成html标签。全部都是在BaseForm这个类里实现的。所以这些功能在ModelForm里一样都有,并且用起来和Form几乎也是一样的。

元类里的参数

讲师的博客地址:http://www.cnblogs.com/wupeiqi/articles/6229414.html

在上面的例子中,已经用的了3个参数了,model、fields、exclude。下面看见一共有哪些常用的参数:

model :对应models的哪张表

fields :显示的字段,__all__表示全部字段

exclude :排除的自动

labels :自定义标签名,字典类型 labels = {'username': "名字", 'email': "邮箱", 'user_type': "类型"} 对应上面的例子。如何还在models里设置了verbose_name,还是以这里的labels为准。

help_texts :提示信息,显示在输入框后面。字典类型和上面一样。

widgets :自定义插件,用的还是form的插件,如果直接导入会重名,要加别名 from django.forms import widgets as my_widgets 。用法举例:widgets = {'username': my_widgets.Textarea(attrs={'class': 'c1'})}

error_messages :自定义错误信息,整体错误信息的key是 from django.core.exceptions import NON_FIELD_ERRORS 也就是 '__all__'

field_classes :自定义Form验证的类。默认models里是CharField,那么对于Form的类也是CharField。这个设置可以改掉实现自定义。用法举例:field_classes = {'username': forms.fields.EmailField} 。如果直接导入fields依然会有重名的问题,用as改掉

localized_fields :本地化,根据不同时区显示数据。参数是需要本地化的字段名的元祖,比如:localized_fields=('create_time',)

元类里的很多字段设置都和Form里的用法是一样的。但是Form里是一个字段一个字段设置的,而ModelForm是整张表设置的。所以这里的设置传入的都是字典,key就是字段名,value就是和Form里设置的值一样了。

ModelForm 中 Model 的功能

这里主要就是数据的增删改查了

添加数据

直接获取到对象,用is_valid()方法验证通过后,直接对对象用一个save()方法就能完成数据的添加。下面是可以完成数据添加的处理函数:

# views.py 文件

def user_info(request):

if request.method == 'GET':

obj = forms.UserInfo()

return render(request, 'user_info.html', {'obj': obj})

elif request.method == 'POST':

obj = forms.UserInfo(request.POST)

if obj.is_valid():

obj.save()

return render(request, 'user_info.html', {'obj': obj})

多对多的情况

例子就不写了。如果是有多对多的关联,默认也是会更新多对多关联的第三张表的数据的。

实际上save()方法内部是拆分成2步执行的,先操作当前的这张表,然后去操作多对多关联的第三张表。save()方法有个默认参数 def save(self, commit=True): 默认设置就是上面那样执行的。如果参数是False,就是不帮我们自动更新第三张表。如果要用False参数具体用法如下:

instance = obj.save(False) # 不在任何操作

instance.save() # 保存当前的表的数据

obj.save_m2m() # 保存第三张表的数据

填入默认值

要在生成html的时候,在页面内填入默认值。首先要做一步model操作,去数据库里获取一条数据对象,然后把这个对象作为ModelForm的instance参数传入。代码如下:

if request.method == 'GET':

user_obj = models.UserInfo.objects.filter(id=1).first()

obj = forms.UserInfo(instance=user_obj)

return render(request, 'user_info.html', {'obj': obj})

更新数据

上面填入默认值,在做修改的时候经常会用到。修改完成后提交到后台,就要进行数据更新了。这里不能用直接save()方法,因为这样会变成新建。数据更新用的还是save()方法,但是要再传入一个参数,告诉系统要把新的数据更新到表的哪一条,否则就是新建。具体的做法如下:

elif request.method == 'POST':

user_obj = models.UserInfo.objects.filter(id=1).first()

obj = forms.UserInfo(request.POST, instance=user_obj)

if obj.is_valid():

obj.save()

return render(request, 'user_info.html', {'obj': obj})

这里和上面填入默认值的做法差不多,只不过这里把需要更新的数据也传递进来了。

添加额外的字段

比如一个login登录的应用场景。页面上除了有用户名和密码以外,还可以加一个单选框“记住我”。这个额外的字段是不记录到数据库里的,而是会写到cookie或者session里。这种情况,可以把这个字段定义在ModelForm类里作为公有属性(静态属性),定义的时候完全和定义Form的字段是一样的:

# forms.py 文件

class UserInfo(forms.ModelForm):

is_remembered = forms.fields.CharField(

widget=my_widgets.CheckboxInput(),

label="记住我",

)

class Meta:

# 元类里的内容就略了

这样这个额外的字段在页面里会显示在最后面,有Form的全部功能,验证和生成html。但是不会有model操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值