StackOverflow中提到了很多save()方法的例子。这是我的想法:模型是抽象的。
def save(self, *args, **kwargs):
# take id of 'self' object by: last id + 1 or 1 if there is no objects in db
try:
future_id = int(self.__class__.objects.latest('pk').pk) + 1
except:
future_id = 1
# set slug by id
self.slug = '{future_id}'.format(future_id=future_id)
# set slug by name and id
if self.get_name():
self.slug = '{name}-{slug}'.format(name=slugify(self.get_name()),
slug=self.slug)
# save
super(AbstractCmsContent, self).save(*args, **kwargs)
问题是:我应该在数据库中使用last id准备一些通用表,还是使用latest()函数调用此解决方案应该在实践中运行良好?
我将回答我是如何改变这个功能的。最后,我的函数看起来像这样:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = '{name}'.format(name=slugify(self.get_name()))
objs = self.__class__.objects.filter(slug__startswith=self.slug)
max_index = objs.aggregate(Max('slug_index'))['slug_index__max']
# two conditions:
# max_index should be positive,
# or number of objects with simillar slug in db > 0
if max_index or objs.count()>0:
self.slug_index = max_index + 1
self.slug = "{slug}-{index}".format(slug=self.slug,
index=self.slug_index)
super(AbstractCmsContent, self).save(*args, **kwargs)
第一个slug总是只基于名字,下一个有一些额外的索引:'slug-index'。另外我在我的模型中添加了一些额外的字段slug_index,但是像这样我可以很好地控制我的slu ..
答案 0 :(得分:2)
一般来说,你不应该依赖于获得这样的最新ID,因为有一天你会面临竞争条件(当你的最新PK已经被拿走时)或者你的某些模型会出现错误的ID。
我建议让slug字段可以为空(如果它有unique=True
之类的话,它是唯一的选项)并在super
调用之后填充它。因此,您将通过将所有内容委托给数据库来获得防弹可靠ID并简化代码。此外,如果您使用现代数据库,它将全部发生在事务中,因此您的对象没有任何时间没有slug。
def save(self, *args, **kwargs):
super(AbstractCmsContent, self).save(*args, **kwargs)
self.slug = '{pk}'.format(pk=self.pk)
if self.get_name():
self.slug = '{name}-{slug}'.format(name=slugify(self.get_name()), slug=self.slug)
self.__class__.objects.filter(pk=self.pk).update(slug=self.slug)