如何在 Django 中自定义 slug 字段?

Posted

技术标签:

【中文标题】如何在 Django 中自定义 slug 字段?【英文标题】:How do I customize a slug field in Django? 【发布时间】:2015-07-22 00:53:20 【问题描述】:

我已经检查了this,但我需要连接两个字段中的内容 好的,问题来了。

我有两个模型,brandproduct,看起来像这样:

品牌模型

class Brand(models.Model):
    name = models.CharField(max_length=29)
    website = models.URLField()

    def __unicode__(self):
        return self.name

产品型号

class Product(models.Model):
    brand = models.ForeignKey(Brand)
    name = models.CharField(max_length=140)
    slug = models.SlugField()

    def __unicode__(self):
        return self.name

管理方法

from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    prepopulated_fields = 'slug': ('name',)

模型输入示例:

**Brand**
Name: Example
Website: http://www.example.com

**Product**
Brand: Example (Selection)
Name: Product
Slug: product(prepopulated)

我希望 slug 是 example-product 而不是 product。如何将品牌和名称连接为 slug。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

将品牌添加到 prepopulated_fields 字典仅返回 id 而不是 str/unicode 值。

class ProductAdmin(admin.ModelAdmin):
    prepopulated_fields = 'slug': ('brand', 'name',)

一种方法是添加 save_model 方法 ModelAdmin

from django.utils.text import slugify

class ProductAdmin(admin.ModelAdmin):    
    def save_model(self, request, obj, form, change):
        # don't overwrite manually set slug
        if form.cleaned_data['slug'] == "":
            obj.slug = slugify(form.cleaned_data['brand']) + "-" + slugify(form.cleaned_data['name'])
        obj.save()

【讨论】:

【参考方案2】:

你不能。根据 Django 文档:

prepopulated_fields 不接受 DateTimeField、ForeignKey 或 ManyToManyField 字段。

链接:https://docs.djangoproject.com/en/1.8/ref/contrib/admin/

我试过了:

prepopulated_fields = 'slug': ('brand', 'name')

这将在品牌 ID 后附加名称而不是品牌名称,因此您会得到 '1-product' 而不是 'example-product'


更新:将 slug 字段保存到数据库和在管理页面中显示 slug 字段是两件不同的事情。保存会将字符串保存到数据库中。但 'prepopulated_fields' 仅用于展示。它只会影响管理页面的外观。

【讨论】:

但是必须有某种方法,使用保存功能插入带有连接字符串的 slug 字段,无论如何? (def save(self, *args, **kwargs):) ?? @John prepopulated_fields 的工作方式由一个名为 prepopulate.js 的 javascript 文件定义。它只是拉取存储在品牌下拉列表选项标签的 value 属性中的值并将其放入 slug 文本框中。它与将记录保存到数据库中的save() 方法无关。它们是两种不同的东西。 我的意思是用 js 替换 slugbox 上的 'dummy slug',就在模型对象被保存之前,你知道 js 或 vbs 甚至 python 可以处理代码但只有在 @987654325 时才保存@方法被调用,我要求修改保存方法好,我们关心数据库不太关心管理员。 ;) @John 真的很难理解你在问什么。如果下面的答案回答了您的问题,那就太好了。但奇怪的是,下面答案中包含的信息已经在您原始帖子的链接中。此外,您的prepopulated_fields = 'slug': ('name',) 行完全误导了您真正要问的内容。无论如何,下次问一个更简洁的问题。【参考方案3】:

您可以在产品保存中添加一个 slugify 功能(免责声明:我没有尝试使用外键执行此操作,所以我不是 100% 确定,但此方法对我有效,如果有效,请告诉我给你)。

from unidecode import unidecode
from django.template.defaultfilters import slugify    

class Product(models.Model):
...

    def save(self):
        if not self.id: # if this is a new item
            newslug = '0 1'.format(self.brand__name, self.name)  
            self.slug = slugify(unidecode(newslug))
        super(Product, self).save()

【讨论】:

我已经为另一个应用安装了它,所以在这里使用它对我来说不是问题,但是,它是可选的。

以上是关于如何在 Django 中自定义 slug 字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 1.5 中自定义用户模型

django中自定义表名及字段名称

在Django Admin中将预填充的段塞字段设置为只读

Slug 字段不适用于 django 中的孟加拉语。如何在孟加拉语中使用蛞蝓

django中的Slug字段错误

在 Django 中自定义管理表单,同时使用自动发现