Nothing here
Nothing here

Reputation: 2393

How to change HiddenInput value of form

I am trying to create a url from the title of an object which is given by the user. I figured I could do this in the clean_url method of the form but it does not seem to work.

    def clean_url(self):
        url = re.sub(r'\W+', '', str(self.cleaned_data['title']))
        return url

How can I add form.url data to the form before saving?

Model:

class Quiz(models.Model):
    title = models.CharField(
        verbose_name=_("Title"),
        max_length=60,
        unique=True,
        blank=False)
    receiver = models.ManyToManyField(
        EmployeeType,
        blank=True,
        verbose_name='Employee Type',
        related_name='quiz_receiver')
    description = models.TextField(
        verbose_name=_("Description"),
        blank=True,
        help_text=_("A description of the quiz"))
    url = models.SlugField(
        max_length=60,
        blank=False,
        unique=True,
        help_text=_("e.g. 'blackjackshuffling'"),
        verbose_name=_("User friendly URL"))

Upvotes: 1

Views: 35

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477190

The SlugField is often not specified in a ModelForm, but constructed by the model. One can make use of the slugify function [Django-doc] for that:

class Quiz(models.Model):
    # …
    url = models.SlugField(
        max_length=60,
        blank=False,
        editable=True,
        unique=True,
        help_text=_("e.g. 'blackjackshuffling'"),
        verbose_name=_('User friendly URL')
    )

    def save(self, *args, **kwargs):
        if self.pk is None:
            base_url = url = slugify(self.title)
            i = 0
            while self._meta.model.objects.filter(url=url).exists():
                url = f'{base_url}{i}'
                i += 1
            self.url = url
        super().save(*args, **kwargs)

Perhaps it is however more convenient to use the AutoSlugField [readthedocs] from the django-autoslug package [readthedocs]. You can install this in your virtual environment with:

pip3 install django-autoslug

In your model you can then specify from what field it should populate and let the AutoSlugField handle the rest of the logic:

from autoslug import AutoSlugField

class Quiz(models.Model):
    # …
    url = AutoSlugField(
        populate_from='title',
        unique=True
    )

Upvotes: 2

Related Questions