在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. template <typename T>模板类定义

    #include "stdafx.h"#include "iostream"#include <ctime>using namespace std; ...

  2. Java 高阶 —— try/catch

    // try catch 在 for 循环外 try { for(int i = 0; i < max; i++) { String myString = ...; float myNum = ...

  3. bzoj 3781 小B的询问——分块

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3781 非常经典的分块套路.于是时间空间比大家的莫队差了好多…… #include<io ...

  4. 微信小程序把玩(三十)wx.request(object) API

    这里通过干活集中营的API接口真实请求下数据.如果提示URL 域名不合法,请在 mp 后台配置后重试修改asdebug.js两行代码即可可看下面图 百牛信息技术bainiu.ltd整理发布于博客园 定 ...

  5. 蓝桥杯 2014本科C++ B组 李白打酒 三种实现方法 枚举/递归

    标题:李白打酒 话说大诗人李白,一生好饮.幸好他从不开车. 一天,他提着酒壶,从家里出来,酒壶中有酒2斗.他边走边唱: 无事街上走,提壶去打酒. 逢店加一倍,遇花喝一斗. 这一路上,他一共遇到店5次, ...

  6. 用Merge存储引擎中间件实现MySQL分表

    觉得一个用Merge存储引擎中间件来实现MySQL分表的方法不错. 可以看下这个博客写的很清楚--> http://www.cnblogs.com/xbq8080/p/6628034.html ...

  7. 二维码扫描极速版2.0.apk

    二维码扫描极速版2.0.apk 百度网盘下载地址: http://pan.baidu.com/s/1o686bGI 二维码扫描极速版 描述 二维码扫描极速版,快速识别二维码中的信息. 简单易用. 提高 ...

  8. VS2008给对话框添加背景颜色

    第一种方法如下: 在对话框OnPaint()函数中添加代码 //改变对话框背景颜色 CRect rect; CPaintDC dc(this); GetClientRect(rect); dc.Fil ...

  9. java命令行编译运行、打包jar

    过程:java文件→class文件→exe执行文件 --------------------------------------------- 一.编译:从.java生成.class   (1)ecl ...

  10. Flutter实战视频-移动电商-56.购物车_商品数量控制区域制作

    56.购物车_商品数量控制区域制作 主要做购物车中的数量这里 cart_page文件夹下新建cart_count.dart 减少按钮 因为会有点击事件,所以这里我们使用InkWell. child里面 ...