ProgrammingError:列"product"的类型为product [],但表达式的类型为text [] enum postgres

Dej*_*ell 12 python database django postgresql enums

我想保存一系列枚举.

我有以下内容:

CREATE TABLE public.campaign
(
  id integer NOT NULL,
  product product[]
)
Run Code Online (Sandbox Code Playgroud)

产品是一个enum.

在Django我定义它是这样的:

PRODUCT = (
    ('car', 'car'),
    ('truck', 'truck')
)
class Campaign(models.Model):
    product = ArrayField(models.CharField(null=True, choices=PRODUCT))
Run Code Online (Sandbox Code Playgroud)

但是,当我写下以下内容时:

campaign = Campaign(id=5, product=["car", "truck"])
campaign.save()
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

ProgrammingError: column "product" is of type product[] but expression is of type text[]
LINE 1: ..."product" = ARRAY['car...
Run Code Online (Sandbox Code Playgroud)

注意 我看到了这个答案,但我不使用sqlalchemy,如果不需要,我宁愿不使用它.

编辑 我在下面尝试了@Roman Konoval建议:

class PRODUCT(Enum):
    CAR = 'car'
    TRUCK = 'truck'

class Campaign(models.Model):
        product = ArrayField(EnumField(PRODUCT, max_length=10))
Run Code Online (Sandbox Code Playgroud)

与:

campaign = Campaign(id=5, product=[CAR, TRUCK])
campaign.save()
Run Code Online (Sandbox Code Playgroud)

但是,我仍然得到同样的错误,

我看到django正在将它翻译成字符串列表.如果我直接在psql控制台上编写以下代码:

INSERT INTO campaign ("product") VALUES ('{car,truck}'::product[]) 
Run Code Online (Sandbox Code Playgroud)

它工作得很好

e4c*_*4c5 10

这里有两个基本问题.

不要使用枚举

如果继续使用枚举,那么Stackoverflow上的下一个问题将是"如何向枚举添加新条目?".Django不支持开箱即用的枚举类型(谢天谢地).所以你必须使用第三方库.您的里程数将随着图书馆的完整程度而变化.

枚举值占用磁盘上的四个字节.枚举值的文本标签的长度受编译到PostgreSQL中的NAMEDATALEN设置的限制; 在标准版本中,这意味着最多63个字节.

如果您认为使用枚举节省了磁盘空间,则手册中的上述引用表明这是一种错觉.

有关枚举的优缺点的更多信息,请参阅此问答.但通常缺点超过优点.

不要使用数组

提示:数组不是集合; 搜索特定的数组元素可能是数据库错误设计的标志.考虑为每个将成为数组元素的项使用一个单独的表.这将更容易搜索,并且可能更好地扩展到大量元素.

资料来源:https://www.postgresql.org/docs/9.6/static/arrays.html

如果您要搜索涉及汽车或卡车的广告系列,您将不得不做很多艰苦的工作.数据库也是如此.

正确的设计

正确的设计是postgresql数组文档页面中建议的设计.创建一个相关的表.这也是标准的django方式.

class Campaign(models.Model):
    name = models.CharField(max_length=20)


class Product(Models.model):
    name = models.CharField(max_length=20)
    campaign = models.ForeignKey(Campaign)
Run Code Online (Sandbox Code Playgroud)

这使您的代码更简单.不需要任何额外的存储空间.不需要第三方库.最重要的是django相关型号的广泛api 可供您使用.