Как мне создать слизняк в Django?

175

Я пытаюсь создать 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

Теги:
slug

8 ответов

329

Вам нужно будет использовать функцию 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, которое

  • 4
    у вас есть особый тип модели? почему бы просто не убить CharFields?
  • 23
    SlugFields установить db_index = True по умолчанию, а также использовать поле формы по умолчанию, которое имеет регулярное выражение проверки, чтобы требовать допустимых слагов (если они представлены в ModelForm или в администраторе). Вы можете делать эти вещи вручную с помощью CharField, если вы предпочитаете, это только делает намерение вашего кода менее ясным. Кроме того, не забывайте параметр ModelAdmin prepopulate_fields, если вы хотите автоматически заполнять JP на основе администратором.
Показать ещё 5 комментариев
97

Существует угловой регистр с некоторыми символами 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'
  • 7
    Slugify теперь правильно обрабатывает utf-8 (в django 1.8.5)
  • 0
    Как сказал @RickWestera, теперь это обрабатывается slugify, хотя, если по какой-то причине вы не хотите использовать slugify, проверьте iri_to_uri из django.utils.encoding: docs.djangoproject.com/en/2.0/ref/unicode/…
56

Небольшая поправка на ответ 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 (неожиданный аргумент).

  • 2
    Еще одна очень незначительная вещь, которую нужно добавить в ответ thepeer: я бы заставил эту последнюю строку return super(test, self).save(*args, **kwargs) . Я думаю, что этот метод возвращает None , и я не знаю никаких планов изменить это, но не вредно возвращать то, что делает метод суперкласса, если он изменится когда-нибудь в будущем.
  • 0
    Пожалуйста, добавьте, что из django.utils.text для этого решения требуется импорт slugify .
Показать ещё 2 комментария
28

Если вы используете интерфейс администратора для добавления новых элементов своей модели, вы можете настроить ModelAdmin в своем admin.py и использовать prepopulated_fields для автоматизации ввода пули:

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

admin.site.register(Client, ClientAdmin)

Здесь, когда пользователь вводит значение в форме администратора для поля name, slug будет автоматически заполнен правильным slugified name.

  • 0
    Мои поля slug и name имеют переводы. Как я могу сделать это с переводами? Потому что я попытался добавить 'slug_en':('name_en',) и получил ошибку, что атрибут не существует в моей модели.
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()
  • 9
    должен принимать * args и ** kwargs
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()
  • 5
    или вы можете использовать editable = False: P
  • 0
    Документы на редактирование
4

Используйте prepopulated_fields в вашем классе администратора:

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

admin.site.register(Article, ArticleAdmin)

http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.prepopulated_fields

  • 1
    Могли бы вы объяснить? Как админ влияет на проект?
2

Я использую Django 1.7

Создайте SlugField в вашей модели следующим образом:

slug = models.SlugField()

Затем в admin.py определите prepopulated_fields;

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню