class Product(models.Model):
title = models.CharField(max_length=75)
class Deal(models.Model):
product = models.ForeignKey(Product)
slug = models.SlugField(max_length=255, unique=True)
具有与上面类似的基本设置,我想为每个Deal实例生成唯一的slug,使用它的交易和交易ID的产品标题。 IE:"apple-iphone-4s-161"
其中161
是交易的ID,之前的文本是产品的标题。
为此,如何覆盖Deal模型的save()方法以应用它?
答案 0 :(得分:4)
当然你可以简单地覆盖模型上的save()方法(或者为post_save信号创建接收器)。 它将类似于:
from django.template.defaultfilters import slugify
class Deal(models.Model):
product = models.ForeignKey(Product)
slug = models.SlugField(max_length=255, unique=True)
def save(self, *args, **kwargs):
super(Deal, self).save(*args, **kwargs)
if not self.slug:
self.slug = slugify(self.product.title) + "-" + str(self.id)
self.save()
但是这个解决方案中的丑陋之处在于它会两次击中数据库(它被保存两次)。这是因为在创建新的Deal对象时,在你第一次保存它之前它不会有id(并且你无法做很多事情)。
答案 1 :(得分:2)
我已经碰到了这个问题,并测试了jasisz解决方案,并且得到了最大递归深度超出错误,所以我对它进行了很少的调整,这就是我的看法:
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.title)
super(Node, self).save(*args, **kwargs)
你可以编辑它以满足你的需要,它会测试这些记录是否存在,如果没有则会创建slug字段,否则就是更新而不需要修改slug字段。
希望它有所帮助。答案 2 :(得分:1)
我知道这可能不适合你的情况,但我记得碰到类似的情况。我想我的模型中有created_at
字段auto_now=True
。或类似的东西
我的slug看起来像这样
self.slug = '%s-%s' %(
slugify(self.title),
self.created_at
)
或者你可以
self.slug = '%s-%s' %(
slugify(self.title),
datetime.datetime.now()
)
只需确保slu max_length
足够长,以包含完整的created_at
时间,以及title
,这样您就不会得到非唯一的或超过最大长度例外。
答案 3 :(得分:1)
您应该完全不在该子弹字段中输入ID。造成这种情况的两个主要原因是:
但是对于您的问题有一个简单的解决方案:将段塞存储在数据库中的唯一原因是,您可以按段查找一行。但是您不需要-您具有ID。因此,您应该这样做:
class DealManager(models.Manager):
def get_by_slug(slug):
return self.get(id=slug.rsplit('-', 1)[1])
class Deal(models.Model):
product = models.ForeignKey(Product)
slug = models.SlugField(max_length=255, unique=True)
objects = DealManager()
@property
def slug(self):
return slugify(f'{self.name}-f{self.id}')
在您看来或需要从某处检索某物品的任何地方,您都可以执行Deal.objects.get_by_slug(slug)
。