Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 这种行为是否记录在Django';s外键的字段验证器?_Python_Django - Fatal编程技术网

Python 这种行为是否记录在Django';s外键的字段验证器?

Python 这种行为是否记录在Django';s外键的字段验证器?,python,django,Python,Django,这是Python 2代码的一个示例: from django.db import models def my_validator(value): assert isinstance(value, (int, long)) class Foo(models.Model): name = models.CharField(...) # irrelevant here class Bar(models.Model): name = models.CharField(...

这是Python 2代码的一个示例:

from django.db import models

def my_validator(value):
    assert isinstance(value, (int, long))

class Foo(models.Model):
    name = models.CharField(...) # irrelevant here

class Bar(models.Model):
    name = models.CharField(...) # irrelevant here
    foo = models.ForeignKey(Foo, validators=[my_validator])
如果创建一个Foo实例,然后创建一个Bar实例(分配Foo实例),然后进行验证,则此代码会传递:要验证的FK值不是模型实例,而是一个ID(默认情况下为整数):

Edit:我忘了包含
full\u clean()
调用。但是是的:麻烦的代码调用
full\u clean()
。事实上,我第一次注意到这种行为是在尝试将validator callable中的
视为模型实例而不是原始值时,这在尝试调用validator中的实例方法时触发了
int value has no attribute xxx

bar.full_clean()

这发生在Django 1.9中。这是否已记录在案并符合要求?

是-这在以下文件中被隐式提及:

相关对象上与该关系相关的字段。默认情况下,Django使用相关对象的主键

此外:

对于映射到模型实例的
ForeignKey
等字段,默认值应为它们引用的字段的值(
pk
,除非设置了
to_field
),而不是模型实例

也就是说,默认情况下,
外键
是相关对象的主键,即整数

但是,您可以指定不同的
to_字段
,在这种情况下,
值将采用该字段的类型


就传递给验证器的值而言,似乎假设这是
to_字段
(除了要存储在数据库中的值之外,您还要验证什么?在验证外键时传递模型对象没有多大意义,因为该键本身只是指向该对象的指针,并且没有说明该对象应该是什么。)


但为了回答您的问题-似乎没有任何明确的文档说明这一点。

是-文档中暗指这一点:

关系所指向的相关对象上的字段。默认情况下,Django使用相关对象的主键

此外:

对于映射到模型实例的
ForeignKey
等字段,默认值应为它们引用的字段的值(
pk
,除非设置了
to_field
),而不是模型实例

也就是说,默认情况下,
外键
是相关对象的主键,即整数

但是,您可以指定不同的
to_字段
,在这种情况下,
值将采用该字段的类型


就传递给验证器的值而言,似乎假设这是
to_字段
(除了要存储在数据库中的值之外,您还要验证什么?在验证外键时传递模型对象没有多大意义,因为该键本身只是指向该对象的指针,并且没有说明该对象应该是什么。)


但是要回答你的问题-似乎没有任何明确的文档说明这一点。

我不确定@solarissmoke的答案是否与该问题相关

IMO不会在
对象上调用。创建
,如果要在创建模型之前验证模型,应使用
模型表单
,或手动调用它

foo = Foo.objects.create(name='foo')

bar = Bar(name='bar', foo=foo)

try:
    bar.full_clean()
    bar.save()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.
    pass
更新: 好的,那么确切的情况是,当你打电话给我们时,我们会接到电话

clean_字段中
有如下内容:

raw_value = getattr(self, f.attname)
if f.blank and raw_value in f.empty_values:
    continue
try:
    setattr(self, f.attname, f.clean(raw_value, self))
except ValidationError as e:
    errors[f.name] = e.error_list
value = self.to_python(value)
self.validate(value)
self.run_validators(value)
return value
发生两件事:

  • 我们得到字段的
    原始值
  • 我们调用
    field.clean
  • 字段.clean()
    中,我们有,
    validate()
    .run\u validators()
    按以下顺序调用:

    raw_value = getattr(self, f.attname)
    if f.blank and raw_value in f.empty_values:
        continue
    try:
        setattr(self, f.attname, f.clean(raw_value, self))
    except ValidationError as e:
        errors[f.name] = e.error_list
    
    value = self.to_python(value)
    self.validate(value)
    self.run_validators(value)
    return value
    
    Django在这里解释道:

    但是,这不是在自定义的
    验证器中获得
    int/long
    的原因

    这是因为
    ForeignKey
    属性中的字段末尾带有
    \u id
    ,等于
    f.attname
    。因此,在验证
    FKs
    Django的整个过程中,Django使用的是
    int/long
    值,而不是对象


    如果您看到该方法,您会发现它只是检查id为
    的行是否存在

    我不确定@solarismoke答案是否与问题相关

    IMO不会在
    对象上调用。创建
    ,如果要在创建模型之前验证模型,应使用
    模型表单
    ,或手动调用它

    foo = Foo.objects.create(name='foo')
    
    bar = Bar(name='bar', foo=foo)
    
    try:
        bar.full_clean()
        bar.save()
    except ValidationError as e:
        # Do something based on the errors contained in e.message_dict.
        # Display them to a user, or handle them programmatically.
        pass
    
    更新: 好的,那么确切的情况是,当你打电话给我们时,我们会接到电话

    clean_字段中
    有如下内容:

    raw_value = getattr(self, f.attname)
    if f.blank and raw_value in f.empty_values:
        continue
    try:
        setattr(self, f.attname, f.clean(raw_value, self))
    except ValidationError as e:
        errors[f.name] = e.error_list
    
    value = self.to_python(value)
    self.validate(value)
    self.run_validators(value)
    return value
    
    发生两件事:

  • 我们得到字段的
    原始值
  • 我们调用
    field.clean
  • 字段.clean()
    中,我们有,
    validate()
    .run\u validators()
    按以下顺序调用:

    raw_value = getattr(self, f.attname)
    if f.blank and raw_value in f.empty_values:
        continue
    try:
        setattr(self, f.attname, f.clean(raw_value, self))
    except ValidationError as e:
        errors[f.name] = e.error_list
    
    value = self.to_python(value)
    self.validate(value)
    self.run_validators(value)
    return value
    
    Django在这里解释道:

    但是,这不是在自定义的
    验证器中获得
    int/long
    的原因

    这是因为
    ForeignKey
    属性中的字段末尾带有
    \u id
    ,等于
    f.attname
    。因此,在验证
    FKs
    Django的整个过程中,Django使用的是
    int/long
    值,而不是对象


    如果您看到该方法,您会发现它只是检查id为
    的行是否存在

    对不起!我忘了包含完整的\u clean调用。但是是的,我调用了它。“Django使用int/long值,而不是对象。”…这