O
O
ogreshrek2019-10-06 00:27:20
Django
ogreshrek, 2019-10-06 00:27:20

How to generate unique slug for ManyToMany relationship?

Good afternoon! I am doing an educational project about musicians and their releases.
My question is this:
I have a musician and release model. A release may have multiple musicians.
I want each release to have a unique slug consisting of {автор}-{название релиза}if there is one author and {автор}-{автор}-...-{название релиза}if there is more than one author.
Here are my models:

class Musician(models.Model):
    name = models.CharField(verbose_name='Название', 
        blank=False, unique=True
        )

    slug_name = models.SlugField(verbose_name='Слаг', 
        blank=True, unique=True)

    def slugify_name(self):
        """
        Обновляет слаг при сохранении.
        """
        self.slug_name = slugify(self.name)

    def save(self, *args, **kwargs):
        self.slugify_name()
        super().save(*args, **kwargs)

class Release(models.Model):
    author = models.ManyToManyField(
        Musician, 
        verbose_name='Автор', related_name='releases')

    name = models.CharField(
        verbose_name='Название', blank=False,
        )

    slug_name = models.SlugField(verbose_name='Слаг', 
        blank=True, unique=True)

    def get_author_slug(self):
        """
        Возвращает всех авторов релиза в формате '{автор}-{автор}-...'
        """
        if len(self.author.all()) == 1:
            return slugify(''.join([str(a) for a in self.author.all()]))
        else:
            return slugify('-'.join([str(a) for a in self.author.all()]))

    def get_slug(self):
        """
        Генерирует слаг в формате {автор}-{автор}-...-{название релиза}
        """
        author = self.get_author_slug()
        name = self.get_name_slug()
        self.slug_name = slugify(author + '-' + name)

    def slugify_name(self):
        """
        Генерирует слаг в формате {название релиза}-{id}
        """
        self.slug_name = slugify('{}-{}'.format(self.name, self.id))

def create_slug_name(sender, instance, created, **kwargs):
    if created:
        instance.slugify_name()
        instance.save()

post_save.connect(create_slug_name, sender=Release)

At the moment what I have.
I have methods in the release model:
get_author_slug(), get_slug(), and signal create_slug_name
The method get_slug()creates the entire unique slug, which is what I want. The problem is that this method can only be used in the shell , after creating a release with a unique slug.
The signal generates a slug in the format {название релиза}-{id}. Unique - yes, but not what you need.
What can you think of so that the slug is created every time you create / change the name of the release.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
Y
Yura Khlyan, 2019-10-07
@ogreshrek

The signal must be called on m2m-changed

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question