如何在 Django 中创建 slug?

2025-04-15 09:19:00
admin
原创
22
摘要:问题描述:SlugField我正在尝试在 Django 中创建一个。我创建了这个简单的模型:from django.db import models class Test(models.Model): q = models.CharField(max_length=30) s = model...

问题描述:

SlugField我正在尝试在 Django 中创建一个。

我创建了这个简单的模型:

from django.db import models

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

然后我这样做:

>>> from mysite.books.models import Test
>>> t=Test(q="aa a a a", s="b b b b")
>>> t.s
'b b b b'
>>> t.save()
>>> t.s
'b b b b'

我期待着b-b-b-b


解决方案 1:

您将需要使用slugify函数。

>>> from django.template.defaultfilters import slugify
>>> slugify("b b b b")
u'b-b-b-b'
>>>

您可以slugify通过重写save方法自动调用:

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()
    
    def save(self, *args, **kwargs):
        self.s = slugify(self.q)
        super(Test, self).save(*args, **kwargs)

请注意,上述操作会导致您的 URL 在q编辑字段时发生变化,从而导致链接失效。建议您在创建新对象时只生成一次 slug:

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()
    
    def save(self, *args, **kwargs):
        if not self.id:
            # Newly created object, so set slug
            self.s = slugify(self.q)

        super(Test, self).save(*args, **kwargs)

解决方案 2:

存在一些 UTF-8 字符的极端情况

例子:

>>> from django.template.defaultfilters import slugify
>>> slugify(u"test ąęśćółń")
u'test-aescon' # there is no "l"

这个问题可以用Unidecode来解决

>>> from unidecode import unidecode
>>> from django.template.defaultfilters import slugify
>>> slugify(unidecode(u"test ąęśćółń"))
u'test-aescoln'

解决方案 3:

对Thepeer 的回答进行一点修正:要覆盖save()模型类中的函数,最好向其添加参数:

from django.utils.text import slugify

def save(self, *args, **kwargs):
    if not self.id:
        self.s = slugify(self.q)

    super(test, self).save(*args, **kwargs)

否则,test.objects.create(q="blah blah blah")将导致force_insert错误(意外参数)。

解决方案 4:

ModelAdmin如果您使用管理界面添加模型的新项目,则可以在您的模型中设置admin.py并利用prepopulated_fields它自动输入 slug:

class ClientAdmin(admin.ModelAdmin):
    prepopulated_fields = {'slug': ('name',)}

admin.site.register(Client, ClientAdmin)

在这里,当用户在管理表单中输入字段的值时nameslug将自动填充正确的 slugified name

解决方案 5:

在大多数情况下,slug 不应该改变,因此您实际上只想在第一次保存时计算它:

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField(editable=False) # hide from admin

    def save(self):
        if not self.id:
            self.s = slugify(self.q)

        super(Test, self).save()

解决方案 6:

如果您不想将 slugfield 设置为不可编辑,那么我认为您需要将 Null 和 Blank 属性设置为 False。否则,您在管理控制台中尝试保存时会出错。

因此,对上述示例的修改将是:

class test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField(null=True, blank=True) # Allow blank submission in admin.

    def save(self):
        if not self.id:
            self.s = slugify(self.q)

        super(test, self).save()

解决方案 7:

prepopulated_fields在您的管理类中使用:

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

admin.site.register(Article, ArticleAdmin)

解决方案 8:

我正在使用 Django 1.7

像这样在模型中创建一个 SlugField:

slug = models.SlugField()

然后在admin.py定义prepopulated_fields

class ArticleAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("title",)}

解决方案 9:

您可以查看文档,SlugField以更具描述性的方式了解更多信息。

解决方案 10:

您可以使用SlugField()slug创建字段并使用slugify()对字段值进行 slugify,然后在每次添加和更改对象时将 slugify 的字段值保存为覆盖的save()中的字段值,如下所示:name`nameslugProduct`

# "models.py"

from django.utils.text import slugify

class Product(models.Model):
    name = models.CharField(max_length=20)
    slug = models.SlugField()
    
    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)

并且,您可以通过在 URL 中使用in addition 来防止链接断开,如下所示:id`slug`

                         # ↓ "slug" ↓
http://myshop.com/product/orange-juice/id
                                 # "id" ↑

因此,urlid除了需要slugin之外还需要其他内容urls.py,如下所示:

# "urls.py"

urlpatterns = [
    path(      # ↓ "slug" ↓ 
        'product/<slug:slug>/<int:id>/', 
        views.get_product, # ↑ "id" ↑
        name="get_product"
    )
]

然后,您应该只治疗id不治疗slugget_product()如下views.py所示:

# "views.py"

def get_product(request, id=None, slug=None):
    product_obj = None

    if id:
        product_obj = Product.objects.get(id=id)
    
    return HttpResponse(product_obj)

解决方案 11:

在某些情况下,slugify 单独使用不够。我正在使用另一种技术来处理 slug。我认为这应该可以覆盖大多数情况。

首先在您的应用程序目录中创建一个 slug.py 文件,并将以下代码复制到其中。

slug.py

import re
from django.template.defaultfilters import slugify


def unique_slugify(instance, value, slug_field_name='slug', queryset=None,
                   slug_separator='-'):
    """
    Calculates and stores a unique slug of ``value`` for an instance.
    ``slug_field_name`` should be a string matching the name of the field to
    store the slug in (and the field to check against for uniqueness).
    ``queryset`` usually doesn't need to be explicitly provided - it'll default
    to using the ``.all()`` queryset from the model's default manager.
    """
    slug_field = instance._meta.get_field(slug_field_name)

    slug = getattr(instance, slug_field.attname)
    slug_len = slug_field.max_length

    # Sort out the initial slug, limiting its length if necessary.
    slug = slugify(value)
    if slug_len:
        slug = slug[:slug_len]
    slug = _slug_strip(slug, slug_separator)
    original_slug = slug

    # Create the queryset if one wasn't explicitly provided and exclude the
    # current instance from the queryset.
    if queryset is None:
        queryset = instance.__class__._default_manager.all()
    if instance.pk:
        queryset = queryset.exclude(pk=instance.pk)

    # Find a unique slug. If one matches, at '-2' to the end and try again
    # (then '-3', etc).
    next = 2
    while not slug or queryset.filter(**{slug_field_name: slug}):
        slug = original_slug
        end = '%s%s' % (slug_separator, next)
        if slug_len and len(slug) + len(end) > slug_len:
            slug = slug[:slug_len-len(end)]
            slug = _slug_strip(slug, slug_separator)
        slug = '%s%s' % (slug, end)
        next += 1

    setattr(instance, slug_field.attname, slug)


def _slug_strip(value, separator='-'):
    """
    Cleans up a slug by removing slug separator characters that occur at the
    beginning or end of a slug.
    If an alternate separator is used, it will also replace any instances of
    the default '-' separator with the new separator.
    """
    separator = separator or ''
    if separator == '-' or not separator:
        re_sep = '-'
    else:
        re_sep = '(?:-|%s)' % re.escape(separator)
    # Remove multiple instances and if an alternate separator is provided,
    # replace the default '-' separator.
    if separator != re_sep:
        value = re.sub('%s+' % re_sep, separator, value)
    # Remove separator from the beginning and end of the slug.
    if separator:
        if separator != '-':
            re_sep = re.escape(separator)
        value = re.sub(r'^%s+|%s+$' % (re_sep, re_sep), '', value)
    return value

然后在 models.py 文件中导入 unique_slugify。然后在 save() 方法中使用它。

模型.py

from django.db import models
from yourapp.slug import unique_slugify # Change "yourapp" with your app name

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()

    def save(self, **kwargs):
        slug = '%s' % (self.q)
        unique_slugify(self, slug)
        super(Test, self).save()
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用