关于数据库设计:Django模型中的Nullable TextField或空字符串?

Nullable TextField or empty string in Django model?

正如我从这个数据库设计问题中了解到的,您应该谨慎地使用可空字段,并且每次都要对重新考虑数据设计是否更好做出权衡决定。

但是,让我们假设在某些特定情况下,解决方案是允许文本字段包含空值。例如,有user表,有short_bio列,由django的textfield表示,不是强制的。创建一个单独的user_bio表是没有意义的,对吧?

现在的问题是,空值应该是空字符串还是空标记?每个选项的优缺点是什么?在django如何处理数据库方面有什么具体的细节可以改变吗?

应该注意的是,Django Lint目前使用null=True报告charfield和textfield实例。

相反,一些开发人员认为,为字段保留空白存储空字符串是一个坏主意。


我认为,当"空字符串"表示"无值"时,应使用空字符串,以避免将空值和空值混淆,这意味着相同的事情(例如,在搜索或比较时:在某些DBMS中,不能直接将空值与空值进行比较,必须使用IS NULL运算符)。

在使用"short"bio而不通过dom的情况下(例如使用objects.values('short_bio')),使用空字符串也可以更容易地在报表和其他内容中"原样"地使用它,而不会在""中转换空字符串。

此外,Django Docs指出:

Avoid using null on string-based fields such as CharField and TextField unless you have an excellent reason. If a string-based field has null=True, that means it has two possible values for"no data": NULL, and the empty string. In most cases, it’s redundant to have two possible values for"no data;" Django convention is to use the empty string, not NULL.


如果需要一个可以为空的文本字段,该字段应该是唯一的,但允许多个空值,那么最好使用空字符串而不是空字符串。

Django始终将空值视为唯一值,同时空字符串始终等于另一个空字符串。请参阅允许在Django和票据9039中为空的唯一字段。

要获得"两个世界中最好的",您可以将空值存储为空值,但通过自定义表单字段显示为空字符串。Mightyhal的(未测试)示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django.db import models


class CharNullField(models.CharField):
    description ="Stores NULL but returns empty string"
    def to_python(self, value):
        # this may be the value right out of the db, or an instance
        if isinstance(value, models.CharField):
            # if an instance, return the instance
            return value
        if value == None:
            # if db has NULL (==None in Python), return empty string
            return""
        else:
            return value # otherwise, return just the value
    def get_db_prep_value(self, value):
        # catches value right before sending to db
        if value =="":
            # if Django tries to save an empty string, send to db None (NULL)
            return None
        else:
            return value # otherwise, just pass the value