在Django中从模型中删除重复段塞的有效方法

时间:2019-03-21 09:55:43

标签: django django-models

在我的Exam模型中,我使用了slug field的{​​{1}}。但是现在,我要使其独特。所以我在我的子弹字段中添加了not unique约束。

由于数据库中有许多包含相同子词的考试数据。这在迁移时会引起问题,因此,我想找到一种有效的方法来查找所有重复的块并使它们唯一。 任何建议和帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可以通过使用更新将唯一值(即PK)附加到块中来合理有效地做到这一点。例如:

from django.db.models import Value, F, CharField
from django.db.models.functions import Concat

duplicates = Exam,objects.values('slug').annotate(slug_count=Count('slug')).filter(slug_count__gt=1)
for dupe in duplicates:
    Exam.objects.filter(slug=dupe['slug']).annotate(
        new_slug=Concat('slug', Value('-'), 'id', output_field=CharField())
    ).update(slug=F('new_slug'))

正如德克(Dirk)所建议的,这应该在单独的数据迁移中完成,在 之前,该段才是唯一的。

答案 1 :(得分:0)

过去我也遇到过类似的问题,这就是我的 hacky 解决问题的方法。

  

唯一性应设置为False

假设下面 models.py

# models.py

from django.db import models
from .utils import unique_slug_generator


# Create your models here.

class ExamManager(models.Manager):
    def slug_it_out(self):
        exams = Exam.objects.all()
        for exam in exams:
            exam.slug = unique_slug_generator(exam)
            exam.save()
        return print('Slugged out')


class Exam(models.Model):
    title = models.CharField(max_length=120, )
    slug = models.SlugField(max_length=120, blank=True, unique=False)

    objects = ExamManager()

我已经在模型管理器类 ExamManager 中创建了函数 slug_it_out ,该函数根据我建议您实现另一个用于生成块的功能。

  

要在创建新模型对象时自动生成,可以使用pre_save或post_save信号

在您的 models.py 旁边,创建一个 utils.py 并添加以下内容。

# utils.py

from django.utils.text import slugify

def unique_slug_generator(instance, new_slug=None):
    slug = slugify(instance.title)
    new_slug = slug
    Klass = instance.__class__
    numb = 1
    while Klass.objects.filter(slug=new_slug).exists():
        new_slug = "{slug}-{num}".format(
            slug=slug,
            num=numb
        )
        numb += 1
    return new_slug

    # This assumes that the slug is generated from the exam title.
    # Appends an incrementing integer to duplicates

要运行ExamManager类中的功能 slug_it_out ,只需转到外壳,

  

python manage.py shell

运行以下内容;

# In the shell,
>>> from exams.models import Exam
>>> Exam.objects.slug_it_out()

您应该在屏幕上看到被淘汰。随时根据需要编辑代码。