由id的Django Unique Slug

时间:2012-08-15 22:07:09

标签: django django-models

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()方法以应用它?

4 个答案:

答案 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。造成这种情况的两个主要原因是:

  1. 它会造成您遇到的问题
  2. 这是数据库中的冗余数据– 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)