django modelform中的self.instance
在stackoverflow上看到一个问题,正好是我疑惑很久的相关问题。
[原问题地址]https://stackoverflow.com/questions/18265023/self-instance-in-django-modelform
What does self.instance in Django ModelForm constructor mean and where can I find a documentation about it?
class MyModelForm(ModelForm):
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
if self.instance:
...
下面有大神回答:
In a ModelForm, self.instance is derived from the model attribute specified in the Meta class. Your self in this context is obviously an instance of your subclass of ModelForm, and self.instance is (and will be on saving the form without errors) an instance of the model class you specified, although you have not done so in your example.
Accessing self.instance in init may not work, though doing so after calling the parent's init probably will. Further, I wouldn't recommend trying to change the instance directly. If you are interested, have a look at the BaseModelForm code on Github. The instance can also be specified when creating a new form via the instance argument.
This is not a generic Python thing. This is something that's defined specifically by ModelForm, in the superclass init
大致意思是:在modelform中,self.instance来源于元类中指定的model属性。你的self明显是这个上下文中ModelForm子类的实例化,而self.instance是(将在没有错误的情况下保存在表单中)你指定的model类的一个实例。尽管你在示例中没有这么做。
直接在__init__中访问self.instance也许不会工作,虽然在调用父类的__init__后可能会生效。此外,我不建议直接更改实例。如果您感兴趣,请查看Github上的BaseModelForm代码。在通过实例参数创建新表单时也可以指定实例。
最后总结下:self.instance不是python中通用的方法,这是以ModelForm形式,在超类的__init__中特别定义的方法。
另一个回答:
You can find the documentation on django's website.
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-clean-method
Just search the page for every reference to "instance", and you should find what you need.
# Load up an instance
my_poll = Poll.objects.get(id=1)
# Declare a ModelForm with the instance
my_form = PollForm(request.POST, instance=my_poll)
# save() will return the model_form.instance attr which is the same as the model passed in
my_form.save() == my_poll == my_form.instance
他提到的是官方文档中关于instance例子,直接看官方的案例,我们可以找到我们问题的答案。
一共有三步,获取并加载一个对象实例,声明一个ModelForm的实例化,save()方法会返回model_form。实例属性与传入的model类型相同。
按照我的理解,这两个回答都指明了self.instance是modelform对象的实例化,包含了对象中的内容,我们可以通过self.instance访问并获取到对象的数据进行操作。关键在于,理清所实例化的对象在代码架构中的来龙去脉。
Fields are single data points, forms are a collection of fields.
思考题:想想为什么在django中form验证要设置clean()方法,它被设计出来的目的是什么?想要实现什么样的效果,在我们的代码结构中应该置于什么样的地位呢?
附录:
1.在django文档中,Model instance reference这部分提到Model.full_clean(exclude=None, validate_unique=True)。
There are three steps involved in validating a model:
- 验证模型字段 - Model.clean_fields()
- 验证模型作为一个整体 - Model.clean()
- 验证字段唯一性 - Model.validate_unique()
All three steps are performed when you call a model's ~Model.full_clean() method。而在我们使用ModelForm时,对 is_valid() 的调用将对表单上包含的所有字段执行这些验证步骤。
在文档的Form and field validation部分也重新讲解了clean()以及full_clean()方法,这是表单验证中最重要的部分!
2.在django文档中,提到了Model.pk属性。
粗略记录下:
For convenience, each model has an ~django.db.models.AutoField named id by default unless you explicitly specify primary_key=True on a field in your model. See the documentation for ~django.db.models.AutoField for more details.
为了方便起见,每个模型都默认有一个名为 id 的 AutoField,除非n你在模型中的字段上明确指定了 primary_key=True。
Regardless of whether you define a primary key field yourself, or let Django supply one for you, each model will have a property called pk. It behaves like a normal attribute on the model, but is actually an alias for whichever attribute is the primary key field for the model. You can read and set this value, just as you would for any other attribute, and it will update the correct field in the model.
无论是自定义主键字段还是django给你提供的,每个model都有一个名为PK 的属性。它是用于model主键字段的别名。你可以像对待其他字段属性一样,读取或设置值,它将更新模型中的正确字段。
3.文档中还提及,防止后台URL硬编码,我们最好在模板中使用 get_absolute_url()
You should avoid building the URL from unvalidated user input, in order to reduce possibilities of link or redirect poisoning::
def get_absolute_url(self):
return '/%s/' % self.name
If self.name is '/example.com' this returns '//example.com/' which, in turn, is a valid schema relative URL but not the expected '/%2Fexample.com/'.
下面是官方文档中列出的两个示例:
<!-- BAD template code. Avoid! -->
<a href="/people/{{ object.id }}/">{{ object.name }}</a> -------bad
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a> ---------good
这里的逻辑是,如果你更改对象的URL结构,即使是一些简单的,如更正拼写错误,您也不想跟踪每个可能创建的URL的地方。所以可以在 get_absolute_url() 中指定一次,并让所有其他代码调用一个地方。
4.在文档的Overriding the clean() method该部分中,提到:
You can override the clean() method on a model form to provide additional validation in the same way you can on a normal form.A model form instance attached to a model object will contain an instance attribute that gives its methods access to that specific model instance.
大意是,您可以在模型表单上覆盖 clean() 方法,用与正常表单上相同的方式实现自定义验证。附加到模型对象的模型表单实例将包含一个 instance 属性,该方法为其提供访问该特定model的实例。
django modelform中的self.instance的更多相关文章
- Django: ModelForm中Meta的fields等成员介绍
class MyForm(forms.ModelForm): realname = forms.CharField() phone = forms.CharField() class Meta: mo ...
- ModelForm 中选择框的数据 以及 instance 参数
ModelForm 中选择框的数据 print(list(self.fields['customer'].choices)) # [('', '---------'), (1, '张飞'), (2, ...
- django Modelform
前言: 为什么要用form去验证呢? 我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理 ...
- python 全栈开发,Day110(django ModelForm,客户管理之 编辑权限(一))
昨日内容回顾 1. 简述权限管理的实现原理. 粒度控制到按钮级别的权限控制 - 用户登陆成功之后,将权限和菜单信息放入session - 每次请求时,在中间件中做权限校验 - inclusion_ta ...
- Django - ModelForm组件
一.ModelForm组件 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,先来一个简单的例子来看一下这个东西怎么用:比如我们的数据库中有这样一张学生表, ...
- 【python】-- Django ModelForm
Django ModelForm Django的ModelForm的验证方式相比较form + Model的验证方式有下列区别: ModelForm没有form + Model的低耦合性 ModelF ...
- django Modelform 使用
前言: 为什么要用form去验证呢? 我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理 ...
- Django ModelForm操作及验证
一.内容回顾 Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = ...
- Django ORM中常用字段和参数
一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...
随机推荐
- noip2005篝火晚会
这是一道不算太难的题,但愚蠢的我并没有想到. 首先,判断无解的情况:他想相邻的不想与他相邻. 然后,构造出合法的数列,因为第一位左边有两种选择,且构造出的环不等价,所以要做两次. (这一点我并没有想清 ...
- hdu-5728 PowMod(数论)
题目链接: PowMod Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) ...
- hdu-5742 It's All In The Mind(数学)
题目链接: It's All In The Mind Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (J ...
- slice 和 splice 区别
splice() 方法与 slice() 方法的作用是不同的,splice() 方法会直接对数组进行修改. slice(start,end) ; start 必需.规定从何处开始选取.如果是负数,那 ...
- AspNetPager样式以及属性帮助文档
帮助文档地址:http://www.webdiyer.com/AspNetPagerDocs/index.html 应用样式:http://www.webdiyer.com/AspNetPagerDe ...
- java:calendar类及一些比较实用的utils(二)
在这里将我在项目中用到的一些关于使用Calendar的utils分享出来,只是一部分,后期遇到好的通用方法会继续添加,以和大家交流学习,如果你还不熟悉这个类的使用,但是急需某个util,可以加群:41 ...
- MongoDB -- 安装(win 10)
1. 下载安装包: mongodb-win32-x86_64-2008plus-ssl-4.0.10-signed.msi https://www.mongodb.com/download-cente ...
- Flutter实战视频-移动电商-03.底部导航栏制作
03.底部导航栏制作 material是谷歌退出的 还有另外的一种:cupertino是IOS的风格 我们底部的导航栏,静态的widget是不合适的,这垃圾我们用到动态的widget 这重新改成动态的 ...
- mysql 、redis的区别
我们知道,mysql是持久化存储,存放在磁盘里面,检索的话,会涉及到一定的IO,为了解决这个瓶颈,于是出现了缓存,比如现在用的最多的 memcached(简称mc).首先,用户访问mc,如果未命中,就 ...
- sfc命令
开始—>运行—>再输入“sfc /scannow”(不含引号),“sfc”是“系统文件检测”程序,它是一个在命令提示符下使用的实用程序,只有是管理员才能使用该程序,这个程序的作用就是检测系 ...