В Django сохранение (переведенного) слага и его уникальность не работает - PullRequest
0 голосов
/ 18 ноября 2018

Я использую Django 1.11 и плагин parler для перевода.Каждый раз, когда я сохраняю слаг, я хочу

  • проверить, если он уже существует
  • обрезать слаг
  • добавить номер
  • проверить снова,если новый слаг существует и так далее

Таким образом, я хочу создать уникальный слаг при сохранении.

models.py:

from parler.models import TranslatableModel
from django.utils.translation import gettext_lazy as _

class Event(TranslatableModel):
    translations = TranslatedFields(
        event_title=models.CharField(_("event title"), max_length=512),
        slug=models.SlugField(_("slug"), help_text=_("Used in the URL of the event page.")),
        description=RichTextUploadingField(blank=True),
        meta={'unique_together': (('language_code', 'slug'),)},
    )

    def save_translation(self, translation, *args, **kwargs):
        """Create a unique slug of 45 Characters + a dash and 4 digits."""
        translation.slug = translation.slug[:50]
        if Event.objects.active_translations(slug=translation.slug).exists():
            # This is true on the first test for no apparent reason.
            i = 0
            while Event.objects.active_translations(slug=translation.slug).exists():
                translation.slug = translation.slug[:44]+'-'+str(i)
                i += 1
        super(Event, self).save_translation(translation, *args, **kwargs)

Thisкод не работает.Он всегда добавляет число к слагу, несмотря ни на что, даже если я ввожу совершенно новый слаг.

1 Ответ

0 голосов
/ 21 ноября 2018

Проблема в том, что save_translation вызывается несколько раз.Мое решение:

def save_translation(self, translation, *args, **kwargs):
    """Create a unique slug build of the title + language code + a number."""
    translation.slug = translation.slug[:50]
    """
    This filter is a bit more complicated.
    If the same slug but with a differen ID alread exists:
        ~Q(id=translation.master_id) & 
        Q(translations__slug=translation.slug)
    Or if the same slug with the same ID but different language already exists:
        Q(id=translation.master_id) & 
        ~Q(translations__language_code=translation.language_code) & 
        Q(translations__slug=translation.slug)
    """
    if Event.objects.filter(
            (~Q(id=translation.master_id) &
             Q(translations__slug=translation.slug)) |
            (Q(id=translation.master_id) &
             ~Q(translations__language_code=translation.language_code) &
             Q(translations__slug=translation.slug))
    ).exists():
        i = 1
        while Event.objects.filter(
                (~Q(id=translation.master_id) &
                 Q(translations__slug=translation.slug)) |
                (Q(id=translation.master_id) &
                 ~Q(translations__language_code=translation.language_code) &
                 Q(translations__slug=translation.slug))
        ).exists():
            # Truncate the slug, if it is too long. This happens, if the
            # initial slug is to long or if the trailing number reaches
            # another digit.
            trunc_number = (4 + ceil(log10(i + 1)))
            if len(translation.slug) + trunc_number > 50:
                translation.slug = translation.slug[:50-trunc_number]

            # Substitute the trailing language code and number with a bigger number.
            translation.slug = re.sub(
                r'(?P<slug_start>.*?)(-(de|en))?(-(\d)+)?$',
                '\g<slug_start>' + '-' + translation.language_code + '-' + str(i),
                translation.slug)
            i += 1
    super(Event, self).save_translation(translation, *args, **kwargs)

Это стало немного длиннее, чем я надеялся, но я думаю, что это работает.

...