Reputation: 1300
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
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
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
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
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