【问题标题】:How do I create a slug in Django?如何在 Django 中创建 slug?
【发布时间】:2010-10-24 16:22:11
【问题描述】:

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

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

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

【问题讨论】:

    标签: python django django-models slug


    【解决方案1】:

    您需要使用slugify 函数。

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

    您可以通过覆盖save 方法自动调用slugify

    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)
    

    请注意,当编辑q 字段时,上述内容会导致您的网址发生更改,即can cause broken links。创建新对象时最好只生成一次 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)
    

    【讨论】:

    • 害羞有一个特殊的模型类型?为什么不直接扼杀 CharFields?
    • SlugFields 默认设置 db_index=True ,并且默认使用具有验证正则表达式的表单字段来要求有效的 slug(如果在 ModelForm 或管理员中表示)。如果您愿意,您可以使用 CharField 手动执行这些操作,这只会让您的代码意图变得不那么清晰。另外,不要忘记 prepopulate_fields ModelAdmin 设置,如果你想在管理员中基于 JS 自动预填充。
    • 正如 Dingle 在下面的回答中所说,您需要将 def save(self): 替换为 def save(self, *args, **kwargs): 以避免在编写 test.objects.create(q="blah blah blah") 之类的内容时引发错误。
    • 请注意,此代码将更新每次保存的 slug。你的 url 会改变,“Cool URIs don't change”w3.org/Provider/Style/URI.html
    • slugify()也可以在django.utils.text.slugify找到,不清楚是什么时候添加的。
    【解决方案2】:

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

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

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

    【讨论】:

    • 我的 slugname 字段有翻译。我怎么能用翻译做到这一点?因为我尝试添加'slug_en':('name_en',) 并得到属性在我的模型中不存在的错误。
    【解决方案3】:

    在大多数情况下,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()
    

    【讨论】:

      【解决方案4】:

      对 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 错误(意外参数)。

      【讨论】:

      • 另一件非常小的事情要添加到同行的答案中:我会写最后一行return super(test, self).save(*args, **kwargs)。我认为这个方法返回None,我不知道有什么改变它的计划,但是如果它在未来的某个时间发生变化,返回超类的方法所做的事情并没有什么坏处。
      • 请添加此解决方案需要 from django.utils.text import slugify
      • @Routhinator 做到了
      • 试探一下这是否仍然是执行此操作的首选方法。
      【解决方案5】:

      如果您不想将 slugfield 设置为不可编辑,那么我相信您会希望将 Null 和 Blank 属性设置为 False。否则,当您尝试在 Admin 中保存时会出现错误。

      所以对上面例子的修改是::

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

      【讨论】:

      【解决方案6】:

      在您的管理员课程中使用prepopulated_fields

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

      【讨论】:

      • 你能解释一下吗?管理员如何影响项目?
      【解决方案7】:

      有一些 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'
      

      【讨论】:

      • utf-8 现在由 slugify 正确处理(在 django 1.8.5 中)
      • 正如@RickWestera 所说,这现在由 slugify 处理,但如果由于某种原因您不想使用 slugify,请检查 django.utils.encoding 中的 iri_to_uri:docs.djangoproject.com/en/2.0/ref/unicode/…
      【解决方案8】:

      我正在使用 Django 1.7

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

      slug = models.SlugField()
      

      然后在admin.py中定义prepopulated_fields;

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

      【讨论】:

      • 正是我想要的
      【解决方案9】:

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

      【讨论】:

        猜你喜欢
        • 2011-01-11
        • 2018-08-12
        • 2014-11-06
        • 2016-05-17
        • 2016-12-05
        • 2015-09-24
        • 2012-04-10
        • 2015-02-26
        • 2021-10-05
        相关资源
        最近更新 更多