MaxDragonheart
MaxDragonheart

Reputation: 1300

Pre-populate slug field into a form field of a Django site

I've create a form for publish a post on a site. Into the model there is a SlugField that is a pre-populated field in admin.py for the title of the post.

forms.py

class TestPostModelForm(forms.ModelForm):
    title = forms.CharField(
                max_length=70,
                label="Titolo",
                help_text="Write post title here. The title must be have max 70 characters",
                widget=forms.TextInput(attrs={"class": "form-control form-control-lg"}),
                )
    slug_post = forms.SlugField(
                    max_length=70,
                    label="Slug",
                    help_text="Slug is a field in autocomplete mode, but if you want you can modify its contents",
                    widget=forms.TextInput(attrs={"class": "form-control form-control-sm"}),
                    )
.....
    class Meta:
        model = TestPostModel
        fields = [
                "title",
                "slug_post",
                "description",
                "contents",
....
                ]

If I create a post from the administration panel the slug is correctly populated automatically, but the same thing don't happen if I create a post from the form. In this second case the post is created but the slug field remain empty.

I've read that I must use slugify for create a pre-populated field into my form but I have not clear in which method I can do this.

Can I have some example?

Upvotes: 0

Views: 3859

Answers (4)

toolman23
toolman23

Reputation: 19

Just wanted to add my two cents as I struggled with this myself with auto getting the slug. The following is an example in forms.py as well as views.py. The if "POST" part is to return back to the homepage. Else present the form.

forms.py

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'intro','body', 'status']

where model of Post has many other fields such as 'slug', 'published', 'created', 'updated', etc.

views.py

def add_post(request):
    if request.method == 'POST':
        #a post was added
        post_form = PostForm(data=request.POST)
        if post_form.is_valid():
            #create a post object but don't save to database yet
            new_post = post_form.save(commit=False)
            #assign the current slug and user to the post
            new_post.author = request.user
            new_post.slug = slugify(new_post.title)
            #save post to database
            new_post.save()
            return HttpResponsePermanentRedirect(reverse('blog:post_list'))
    else:
        post_form = PostForm()
        return render(request, 'blog/post/add_post.html', {'post_form': post_form})

To access the form in the template you can use the following.

HTML

<form method="post">
    {{ post_form.as_p }}
    {% csrf_token %}
    <p><input type="submit" value="Post" style="cursor: pointer;"></p>
</form>

Upvotes: 1

Muhammad Akram
Muhammad Akram

Reputation: 172

class Post(models.Model):
    title = models.CharField(max_length=150)
    image = models.ImageField(upload_to='images/', blank=True)
    date_created = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(unique=True)

def pre_save_slugify_receiver(sender, instance, *args, **kwargs):
    slug = slugify(instance.title)
    instance.slug = slug

pre_save.connect(pre_save_slugify_receiver, sender=Post)

Upvotes: 1

MaxDragonheart
MaxDragonheart

Reputation: 1300

A little precisation on the coderasha indication: it's important to remove the slug field from the form.

In my case:

class TestPostModelForm(forms.ModelForm):
    title = forms.CharField(
                max_length=70,
                label="Titolo",
                help_text="Write post title here. The title must be have max 70 characters",
                widget=forms.TextInput(attrs={"class": "form-control form-control-lg"}),
                )

.....
    class Meta:
        model = TestPostModel
        fields = [
                "title",
                "description",
                "contents",
....
                ]

Upvotes: 0

thepylot
thepylot

Reputation: 261

Here is the example, in your views.py

form = PostForm(request.POST):
   if form.is_valid():
     post = form.save(commit=False)
     post.slug = slugify(post.title)
     post.save()
    ...

Upvotes: 3

Related Questions