在我的Exam
模型中,我使用了slug field
的{{1}}。但是现在,我要使其独特。所以我在我的子弹字段中添加了not unique
约束。
由于数据库中有许多包含相同子词的考试数据。这在迁移时会引起问题,因此,我想找到一种有效的方法来查找所有重复的块并使它们唯一。 任何建议和帮助将不胜感激。
答案 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()
您应该在屏幕上看到被淘汰。随时根据需要编辑代码。