class Foo(models.Model):
title = models.CharField(max_length=20)
slug = models.SlugField()
是否有内置的方式可以使slug字段根据标题自动填充?无论是在管理界面内还是外部。
对于Django 1.0及以上版本的管理员,您需要使用
prepopulated_fields = {'slug': ('title',), }
在您的admin.py中,prepopulated_fields字典中的键是您想要填充的字段,值是您想要连接的字段元组。
在admin之外,您可以在视图中使用slugify函数。在模板中,您可以使用|slugify过滤器。
还有这个包会自动处理这个问题:https://pypi.python.org/pypi/django-autoslug
我想为您提供一份完整且最新的答案,包含需要注意的地方:
如果您只关心在管理员界面中添加和更新数据,您可以简单地使用prepopulated_fields属性。
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
admin.site.register(Article, ArticleAdmin)
如果您使用表单构建了自己的服务器渲染界面,您可以通过使用 |slugify 模板过滤器或在保存表单(is_valid)时使用 slugify 工具来自动填充字段。
上述解决方案仅在通过这些接口(管理界面或自定义表单)操作数据时才会自动填充slugfield(或任何字段)。如果您有API、管理命令或其他任何也能操作数据的功能,您需要转到模型级别。
django-autoslug 提供了 AutoSlugField 字段,它扩展了 SlugField 并允许您设置应该整洁地进行 slugify 的字段:
class Article(Model):
title = CharField(max_length=200)
slug = AutoSlugField(populate_from='title')
最后一种选项是自己实现,需要重载默认的 save() 方法:
该字段使用 pre_save 和 post_save 信号来实现其功能,请查看本答案底部的提示文本。
class Article(Model):
title = CharField(max_length=200)
slug = SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
这是Django初学者常犯的一个误解。首先,您应该知道pre_save和post_save信号与save()方法直接相关。其次,在Django中执行批量更新的不同方式都规避了save()方法,以操作SQL层来实现高性能。这意味着对于以上解决方案3或4中使用的示例模型:
如果要进行批量更新并仍然利用代码级别的约束条件,则唯一的解决方案是逐个迭代对象并调用其save()方法,这比SQL级别的批量操作效率要低得多。当然,您可以在数据库中使用触发器,但那是完全不同的话题。
在管理员之外,可以查看这个django片段。将其放入.save()
中,它将与通过编程创建的对象一起使用。如其他人所说,在管理员内部使用prepopulated_fields
。
prepopulated_fields = {'slug': ('title',), }
使用内置的Django slugify在模型级别自动填充slug字段:
models.py
from django.db import models
class Place:
name = models.CharField(max_length=50)
slug_name = models.SlugField(max_length=50)
signals.py
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.template.defaultfilters import slugify as django_slugify
from v1 import models
@receiver(pre_save, sender=models.Place)
def validate_slug_name(sender, instance: models.Place, **kwargs):
instance.slug_name = django_slugify(instance.name)