Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.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
Django 可选外键应该为NULL还是指向空字符串_Django_Database_Django Models - Fatal编程技术网

Django 可选外键应该为NULL还是指向空字符串

Django 可选外键应该为NULL还是指向空字符串,django,database,django-models,Django,Database,Django Models,当可选的外键缺少外部表中的相关值时,我可以: 将其设置为null 将其指向外部表中的空字符串' 在我看来,如果您遵循Django设计实践,您最终会得到选项2(请参见下面的代码)。这两种方法都有明显的优点或缺点吗 Django在某种程度上出于设计/惯例偏爱2。文档说明null和'是两个可能的“无数据”值。因此,如果省略可选字段,表单将正确验证并提供一个空字符串,您的外键可以指向该字符串。 然而,从逻辑上看,缺少的值似乎意味着null或缺少外键(而不是指向空值的有效外键) 此外,如果我只是列出所有专

当可选的
外键
缺少外部表中的相关值时,我可以:

  • 将其设置为
    null

  • 将其指向外部表中的空字符串
    '

  • 在我看来,如果您遵循Django设计实践,您最终会得到选项
    2
    (请参见下面的代码)。这两种方法都有明显的优点或缺点吗

    Django在某种程度上出于设计/惯例偏爱
    2
    。文档说明
    null
    '
    是两个可能的“无数据”值。因此,如果省略可选字段,表单将正确验证并提供一个空字符串,您的
    外键可以指向该字符串。
    然而,从逻辑上看,缺少的值似乎意味着
    null
    或缺少
    外键
    (而不是指向空值的有效
    外键

    此外,如果我只是列出所有专辑或进行计数,存储空白将是一个难题。每次我都要记得避免使用空字符串。相反,
    null
    外键在相册表中永远不会有条目

    参考:

  • Django docs on

  • 带代码的可选详细信息:

    #models.py
    class Album(Model):
        name = CharField(max_length=50, unique=True)
    
    class Song(Model):
        name = CharField(max_length=50) 
        album = ForeignKey(Album, null=True, blank=True)    
    
    #forms.py
    class SongForm(Form):
        name = CharField(max_length=50)
        album = CharField(max_length=50, required=False)
    
    如果您有一首没有唱片集名称的歌曲,表单将返回
    {'name':'foo','album':'''}
    。这将在
    相册
    表中创建一个名称为空的条目。我可以在视图中绕过这一点(参见下面的代码)。但这似乎是一种黑客行为,因为数据验证应该在表单中完成

    if album:
        Song.objects.create(name=form.cleaned_data['name'], album=form.cleaned_data['album'])
    else:
        Song.objects.create(name=form.cleaned_data['name'], album_id=None)
    

    仔细考虑后,与方法
    1
    相比,方法
    2
    (缺少外部关系意味着对空字符串使用
    FK
    )有一个优势

    使用方法
    2
    将更容易在
    (song.name,song.album)
    上建立一个
    唯一的索引。通过一个例子可以更好地解释这一点。当将空字符串用于相册时,
    Song
    d
    )的两个相似值将被唯一约束捕获。但是,
    null
    在DB中被视为不同的值,在案例1中它们不会被捕获(必须依赖条件索引才能工作)

    我不确定这是故意的还是Django的惯例带来的意外好处

    Missing album => FK is null                    Missing Album => FK points to blank name
    Song  |   Album                                Song  |   Album
    ----------------                               ----------------
    'a'   |    'x'                                 'a'   |    'x' 
    'b'   |    'y'                                 'b'   |    'y'
    'c'   |    'y'                                 'c'   |    'y'
    'd'   |    null                                'd'   |    ''
    'd'   |    null  <- Dup. not caught by DB      'd'   |    ''   <- Duplicate caught by DB
    
    Missing album=>FK为空Missing album=>FK指向空名称
    歌曲|专辑歌曲|专辑
    ----------------                               ----------------
    “a”|“x”a”|“x”
    “b”|“y”“b”|“y”
    ‘c’|‘y’‘c’|‘y’
    “d'| null'd'|”
    
    “d”| nullDjango的惯例是使用
    '
    表示基于文本的字段中缺少数据。然而,对于
    ForeignKeys
    ,Django和其他地方的惯例是通过
    NULL
    (即选项1)表示缺少数据

    您的选项2混淆了没有名字的专辑和没有专辑的歌曲之间的区别。Django的约定涉及不同的方式来表示允许的字段中的数据缺乏。但在您的情况下,没有名字的相册是无效的,因此选项2需要发明一个无效的相册,只是为了给其他型号提供一些参考

    您可以这样写:“将其指向外部表中的空字符串
    。但请注意,外键并不指向外部表中的字段,而是指向整行。假设您在
    相册
    模型中有其他字段(例如,一个
    布尔字段
    是国际的
    ,或者一个
    日期字段
    发布日期
    )。现在,你必须在你神奇的行中为这些字段编造任意的假值,这些字段并不代表一张真正的专辑

    因此,我建议坚持传统的选项1

    在表单中处理这个问题是内置的,而且非常简单。例如,在
    ModelForms
    中,
    ForeignKey
    modelcoocefield
    表示。如果
    ForeignKey
    具有
    blank=True
    null=True
    ,则下拉列表中的一个选项将为空,并且使用该选项保存表单将使相应的数据库字段
    null


    在您的情况下,看起来您让用户直接在
    歌曲
    表单上输入唱片集名称。这很好,但当然你必须有特殊的逻辑来解释这个值并创建合适的模型。上面的示例代码不是黑客攻击,也不是数据验证。验证是否允许空值,这由
    blank=True
    (在模型中)或
    required=False
    (在表单中)控制。

    您能否引用一个文档/示例,或在上面的代码中显示,Django如何通过
    null
    在表单中进行验证来表示
    FK
    。关于
    2
    ,我原则上同意你的观点,但如果我仅仅根据Django文档进行论证,我会说表示“无数据”
    Django约定是使用空字符串,而不是NULL
    。按照这种逻辑,“no name”不是无效的唱片集名称,而是表示缺少数据。最后,通过“指向空字符串”,我知道
    FK
    指向一行,而不是一个字段。另请参见下面我的回答。您引用的约定与基于文本的字段相关(“避免在基于字符串的字段上使用null,例如
    CharField
    TextField
    …”)。与通常规则不同的是,
    NULL
    表示字段中缺少数据。包括
    外键
    。我编辑了答案以回应您对表单的评论。如果你有一个特定的