sqlite 在多列唯一约束Django上批量插入

pqwbnv8z  于 2023-02-23  发布在  SQLite
关注(0)|答案(1)|浏览(205)

假设我们有一个模型

from django.db import models

class Concept(models.Model):
    a = models.CharField(max_length=255)
    b = models.CharField(max_length=255)
    c = models.CharField(max_length=255)
    d = models.CharField(max_length=255)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=('a', 'b'),
                name='first_two_constraint'),
        ]

我想在这个模型上执行bulk_create,这样,在违反'first_two_constraint'的唯一约束时,就会执行更新。
对于sqlite3,特性https://github.com/django/django/blob/main/django/db/backends/sqlite3/features.py#L44强制将unique_fields传递给bulk_create函数,但是,我不清楚应该传递什么https://github.com/django/django/blob/829f4d1448f7b40238b47592fc17061bf77b0f23/django/db/models/query.py#L701
我尝试了约束的名称,但是失败了。跟踪,这是因为unique_fields的列表是特定的字段名称,而约束不会有字段名称。https://github.com/django/django/blob/829f4d1448f7b40238b47592fc17061bf77b0f23/django/db/models/query.py#L768
因此,我不知道如何处理这个问题。
根据sqlite3文档https://www.sqlite.org/lang_conflict.html子标题“REPLACE”,该功能应该是可能的,因为即使是多列,违规仍将是唯一约束违规“当发生UNIQUE或PRIMARY KEY约束违规时...”
有人知道如何使用bulk_create函数处理多列约束吗?或者有人确认,实现这一点的唯一方法是使用原始SQL吗?
我不相信它是有unique_fields=('a', 'b'),因为这将是代表两个独立的列约束,对不对?

gab6jxml

gab6jxml1#

我也有过类似的情况。我的模型字段允许我使用这个hacky解决方案。它起作用了。

class Concept(models.Model):
    a = models.CharField(max_length=255)
    b = models.CharField(max_length=255)
    c = models.CharField(max_length=255)
    d = models.CharField(max_length=255)
    _a_b = models.CharField(max_length=255, editable=False, unique=True)

    def save(self, *args, **kwargs):
        # Not that this won't be helpful when doing a bulk_create so you will 
        # have to set this value when creating the bulk_create objects
        self._a_b = f"{self.a}{self.b}"
        super().save(*args, **kwargs)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=('a', 'b'),name='a_b_constraint'),
        ]

Concept.objects.bulk_create(
    concepts, # make sure to create _a_b in the loop that create this
    update_conflicts=True,
    update_fields=('c','d',),
    unique_fields=('_a_b',)
)

相关问题