5
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)

具有与上述类似的基本设置,我想使用其交易的产品标题和交易本身的 ID 为每个 Deal 实例生成唯一的 slug。IE:交易的ID"apple-iphone-4s-161"在哪里161,前面的文字是产品的标题。

为此,我如何覆盖 Deal 模型的 save() 方法来应用它?

4

4 回答 4

7

当然,您可以简单地覆盖模型上的 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(而且您对此无能为力)。

于 2012-08-15T22:47:50.770 回答
3

我遇到了这个问题并测试了 jasisz 解决方案,并得到了超出最大递归深度的错误,所以我很少摆弄它,这就是我的样子:

def save(self, *args, **kwargs):
    if not self.id:
        self.slug = slugify(self.title)
    super(Node, self).save(*args, **kwargs)

您可以对其进行编辑以满足您的需要,它会测试此记录是否存在,如果不存在则创建 slug 字段,否则会更新并且无需修改 slug 字段。

希望能帮助到你。

于 2012-08-16T19:06:10.413 回答
3

你根本不应该在那个 slug 字段中有你的 id。造成这种情况的两个主要原因是:

  1. 它会造成您遇到的问题
  2. 它是数据库中的冗余数据 – id 已经存储

但是有一个简单的解决方案可以解决您的问题:将 slug 存储在数据库中的唯一原因是您可以逐行查找。但你不需要那个——你有身份证。所以你应该这样做:

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)

    objects = DealManager()

    @property
    def slug(self):
        return slugify(f'{self.name}-f{self.id}')

在您的视图中或任何您需要检索给定 slug 的项目的地方,您只需执行Deal.objects.get_by_slug(slug).

于 2018-12-21T15:14:48.263 回答
2

我知道这可能不完全适合您的情况,但我记得遇到过类似的情况。我想我的created_at模型中有一个字段auto_now=True。或者类似的东西

我的蛞蝓看起来像这样

self.slug = '%s-%s' %(
        slugify(self.title),
        self.created_at
)

或者你可以有

self.slug = '%s-%s' %(
        slugify(self.title),
        datetime.datetime.now()
)

只需确保 slugmax_length的长度足以包括全职created_at以及title,这样您就不会遇到非唯一或超过最大长度的异常。

于 2014-11-05T04:54:36.353 回答