如何在Django中创建一个slug?

Joh*_*hnd 210 python django django-models slug

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

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

from django.db import models

class Test(models.Model):
    q = models.CharField(max_length=30)
    s = models.SlugField()
Run Code Online (Sandbox Code Playgroud)

然后我这样做:

>>> 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'
Run Code Online (Sandbox Code Playgroud)

我在期待bbbb

Bud*_*ddy 396

您将需要使用slugify功能.

>>> from django.template.defaultfilters import slugify
>>> slugify("b b b b")
u'b-b-b-b'
>>>
Run Code Online (Sandbox Code Playgroud)

您可以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)
Run Code Online (Sandbox Code Playgroud)

请注意,上述操作会导致您的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)
Run Code Online (Sandbox Code Playgroud)

  • 默认情况下,SlugFields设置db_index = True,默认情况下还使用表单字段,其具有验证正则表达式以要求有效的slug(如果在ModelForm或管理员中表示).如果您愿意,可以使用CharField手动执行这些操作,这只会使您的代码意图变得不那么清晰.另外,如果您想在管理员中使用基于JS的自动预填充,请不要忘记prepopulate_fields ModelAdmin设置. (23认同)
  • `slugify()`也可以在`django.utils.text.slugify`中找到,当添加它时不清楚. (18认同)
  • 请注意,此代码将更新每次保存的slug.你的网址会改变,"酷URI不会改变"http://www.w3.org/Provider/Style/URI.html (6认同)
  • 害羞有一个特殊的型号?为什么不只是将CharFields击退? (4认同)
  • 正如丁格尔在他的回答中所述,你需要用`def save(self,*args,**kwargs)替换`def save(self):```以避免在编写类似的东西时抛出错误`test.objects.create(q ="blah blah blah")`. (4认同)
  • @mrmagooey它是新的1.5 ...在1.4.5中,slugify方法仍然使用模板过滤器 (2认同)

小智 111

角落里有一些utf-8字符

例:

>>> from django.template.defaultfilters import slugify
>>> slugify(u"test ????ó??")
u'test-aescon' # there is no "l"
Run Code Online (Sandbox Code Playgroud)

这可以通过Unidecode解决

>>> from unidecode import unidecode
>>> from django.template.defaultfilters import slugify
>>> slugify(unidecode(u"test ????ó??"))
u'test-aescoln'
Run Code Online (Sandbox Code Playgroud)

  • 现在通过slugify正确处理utf-8(在django 1.8.5中) (7认同)

Din*_*gle 62

对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)
Run Code Online (Sandbox Code Playgroud)

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

  • 还有一个非常小的事情要添加到同一个人的答案中:我会让最后一行"返回超级(测试,自我).save(*args,**kwargs)".我认为这个方法返回`None`,我不知道有任何改变它的计划,但是如果它在将来的某个时候发生变化,那么返回超类的方法会做什么并没有坏处. (2认同)

hen*_*rym 29

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

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

admin.site.register(Client, ClientAdmin)
Run Code Online (Sandbox Code Playgroud)

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


the*_*eer 22

在大多数情况下,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()
Run Code Online (Sandbox Code Playgroud)


小智 6

使用prepopulated_fields在您的管理类:

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

admin.site.register(Article, ArticleAdmin)
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下吗?管理员如何影响项目? (3认同)

小智 5

如果您不想将slugfield设置为Not ed editable,那么我相信您需要将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()
Run Code Online (Sandbox Code Playgroud)