在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的更多相关文章

  1. Django: ModelForm中Meta的fields等成员介绍

    class MyForm(forms.ModelForm): realname = forms.CharField() phone = forms.CharField() class Meta: mo ...

  2. ModelForm 中选择框的数据 以及 instance 参数

    ModelForm 中选择框的数据 print(list(self.fields['customer'].choices)) # [('', '---------'), (1, '张飞'), (2, ...

  3. django Modelform

    前言: 为什么要用form去验证呢? 我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理 ...

  4. python 全栈开发,Day110(django ModelForm,客户管理之 编辑权限(一))

    昨日内容回顾 1. 简述权限管理的实现原理. 粒度控制到按钮级别的权限控制 - 用户登陆成功之后,将权限和菜单信息放入session - 每次请求时,在中间件中做权限校验 - inclusion_ta ...

  5. Django - ModelForm组件

    一.ModelForm组件 这是一个神奇的组件,通过名字我们可以看出来,这个组件的功能就是把model和form组合起来,先来一个简单的例子来看一下这个东西怎么用:比如我们的数据库中有这样一张学生表, ...

  6. 【python】-- Django ModelForm

    Django ModelForm Django的ModelForm的验证方式相比较form + Model的验证方式有下列区别: ModelForm没有form + Model的低耦合性 ModelF ...

  7. django Modelform 使用

    前言: 为什么要用form去验证呢? 我们提交的是form表单,在看前端源码时如果检查到POST URL及我们提交的字段,如果没有验证我们是否可以直接POST数据到URL,后台并没有进行校验,直接处理 ...

  8. Django ModelForm操作及验证

    一.内容回顾 Model - 数据库操作 - 验证 class A(MOdel): user = email = pwd = Form - class LoginForm(Form): email = ...

  9. Django ORM中常用字段和参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

随机推荐

  1. Java笔记(四)

    13. 集合框架: 集合中存储的都是对象的引用(地址) 迭代器:集合的取出元素的方式 import java.util.ArrayList; import java.util.Iterator; pu ...

  2. 关闭页面,window.onunload事件未执行的原因

    1.问题描述: JS中定义widow.onunload= function(),页面关闭时,logout()函数未执行. window.onunload = function() { logout() ...

  3. poj2226Muddy Fields——二分图匹配

    题目:http://poj.org/problem?id=2226 把行连通块作为左部点,列连通块作为右部点,行列连通块有相交的格子就连边: 则问题转化为求最小点覆盖,即最大匹配. 代码如下: #in ...

  4. android jni java类型与c语言类型互换

    1.java String转换 C str char* Jstring2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsst ...

  5. Attributes.Add用途与用法

    Attributes.Add("javascript事件","javascript语句"); 如: this.TextBox1.Attributes.add(& ...

  6. Node.js学习(第四章:初见express)

    Express框架是一款简洁而灵活的node.js web应用框架.前面我们自己手动创建服务器在Express中就是一个API的事情,这就使得我们更加注重业务的功能和开发效率上,不必纠结过多底层的事情 ...

  7. POJ3264 【RMQ基础题—ST-线段树】

    ST算法Code: //#include<bits/stdc++.h> #include<cstdio> #include<math.h> #include< ...

  8. uoj#283. 直径拆除鸡(构造)

    传送门 好神的构造题 vfk巨巨的题解 //minamoto #include<bits/stdc++.h> #define R register #define fp(i,a,b) fo ...

  9. Integrated Metabolomics and Lipidomics Analyses Reveal Metabolic Reprogramming in Human Glioma with IDH1 Mutation (文献分享一组-黄旭蕾)

    题目:Integrated Metabolomics and Lipidomics Analyses Reveal Metabolic Reprogramming in Human Glioma wi ...

  10. Validation(4)-临时

    使用Hibernate-Validator优雅的校验参数 2019年01月01日 13:17:31 余生之君 阅读数:337    版权声明:本文为博主原创文章,未经博主允许不得转载. https:/ ...