Reputation: 15
So i have been trying to add Tags using django-taggit, but for some reason tags are not saving to the database when i try to upload a post using website but it works perfectly with django admin(Tags are saving to the database).
Also when i go to my Post_edit view and try to update empty tags field then it works. In other words, tags are only saving to the database when i try to edit it using Postedit view or upload it using admin. I want it to save to the database using PostUpload view only(like i have to use PostEdit view for every post to display tags). I think there's something wrong either with my view or form.
Also i can see request.POST data is returning the list of Tags on the terminal and form returns no errors.
Everything else is saving to the database except Tags.
here's my code
Views.py
@login_required(login_url="/login/")
def post_upload(request):
index1 = Blog.objects.all().order_by('-time')[0]
content = request.POST.get('content')
title = request.POST.get('title')
image = request.FILES.get('image')
if request.method == 'POST':
post_form = PostUpload(request.POST, request.FILES, instance=request.user)
if post_form.is_valid():
tags = post_form.cleaned_data['tags']
context = post_form.cleaned_data['context']
excerpt_type = post_form.cleaned_data['excerpt_type']
ins = Blog.objects.create(user=request.user, content=content, title=title, image=image, context=context,
tags=tags, excerpt_type=excerpt_type)
ins.save()
messages.success(request, 'Your Post has been successfully posted')
print(request.POST)
print(tags)
return HttpResponseRedirect(reverse('post_upload'))
else:
print(f'error in {request.POST}')
else:
post_form = PostUpload(instance=request.user)
context = {'post_form': post_form, 'index1': index1}
return render(request, 'post_upload.html', context)
@login_required(login_url="/login/")
def post_edit(request, pk):
index1 = Blog.objects.all().order_by('-time')[0]
post = get_object_or_404(Blog, pk=pk)
user = request.user
if request.method == 'POST':
edit_form = PostEdit(request.POST or None, request.FILES, instance=post)
if edit_form.is_valid():
edit_form.save()
print(request.POST)
messages.success(request, 'Your Post has been updated successfully')
return HttpResponseRedirect(post.get_absolute_url())
else:
edit_form = PostEdit(instance=post)
context = {'edit_form': edit_form, 'post': post, 'user': user, 'index1': index1}
return render(request, 'post_edit.html', context)
class Blog(models.Model):
sno = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
content = RichTextUploadingField()
views = models.PositiveIntegerField(default=0)
image = models.ImageField(upload_to='images/', blank=True, default="/static/img/900x300.png")
slug = AutoSlugField(populate_from='title', unique=True, unique_with='title')
time = models.DateTimeField(auto_now_add=True)
excerpt_type = models.ForeignKey(Excerpt, on_delete=models.CASCADE, null=True, blank=True)
context = models.CharField(max_length=20, null=True, blank=True)
tags = TaggableManager()
@property
def image_url(self):
if self.image and hasattr(self.image, 'url'):
return self.image.url
else:
return "/static/images/900x300.png"
@property
def get_month_name(self):
if self.time.month == 1:
return 'January'
elif self.time.month == 2:
return 'February'
elif self.time.month == 3:
return 'March'
elif self.time.month == 4:
return 'April'
elif self.time.month == 5:
return 'May'
elif self.time.month == 6:
return 'June'
elif self.time.month == 7:
return 'July'
elif self.time.month == 8:
return 'August'
elif self.time.month == 9:
return 'September'
elif self.time.month == 10:
return 'October'
elif self.time.month == 10:
return 'November'
elif self.time.month == 12:
return 'December'
def __str__(self):
return self.title + ' by ' + self.user.username
def get_absolute_url(self):
return reverse("posts:posts", args=[str(self.slug)])
class PostUpload(forms.ModelForm):
class Meta:
model = Blog
exclude = ['slug', 'user', 'views']
class PostEdit(forms.ModelForm):
class Meta:
model = Blog
exclude = ['slug', 'user', 'views']
{% if tag %}
<div class="sidebar-box ftco-animate">
<h3>Tag Cloud</h3>
<div class="tagcloud">
{% for tag in Blog.tags.all %}
<a href="{% url 'tagged' tag.slug %}" class="tag-cloud-link">{{ tag }}</a>
{% endfor %}
</div>
</div>
{% endif %}
{% block body %}
<div class="container rounded bg-white mt-5 mb-5">
<div class="col-md-8 mt-3">
<form class="form-group" action="./" method="post" enctype="multipart/form-data" >
{% csrf_token %}
<label for="validationDefaultUsername">Username</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupPrepend2">@</span>
</div>
<input name="username" type="text" class="form-control" id="validationDefaultUsername"
value="{{ user.username }}" aria-describedby="inputGroupPrepend2" disabled>
</div>
{{ post_form.errors | as_crispy_errors }}
{{ post_form.media }}
{{ post_form | crispy }}
<input type="submit" value="Save changes" class="btn" style="color: blueviolet;">
</form>
</div>
</div>
</div>
{% endblock body %}
{% block body %}
<div class="container rounded bg-white mt-5 mb-5">
<div class="col-md-8 mt-3 mb-3">
<form method="post" enctype="multipart/form-data" class="form-group">
{% csrf_token %}
<label for="validationDefaultUsername">Username</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupPrepend2">@</span>
</div>
<input name="username" type="text" class="form-control" id="validationDefaultUsername"
value="{{ user.username }}" aria-describedby="inputGroupPrepend2" disabled>
</div>
{{ edit_form.errors }}
{{ edit_form.media }}
{{ edit_form | crispy }}
<input type="submit" value="Save changes" class="btn" style="color: blueviolet;">
</form>
</div>
</div>
{% endblock body %}
Upvotes: 1
Views: 553
Reputation: 108
You have to save the object first then split the tag values by comma and then add the tags into the field of your object this way. I have added the comments for your understanding. Views.py Uploading Posts( views.py )
@login_required(login_url="/login/")
def post_upload(request):
index1 = Blog.objects.all().order_by('-time')[0]
content = request.POST.get('content')
title = request.POST.get('title')
image = request.FILES.get('image')
if request.method == 'POST':
post_form = PostUpload(request.POST, request.FILES, instance=request.user)
if post_form.is_valid():
tags = post_form.cleaned_data['tags']
context = post_form.cleaned_data['context']
excerpt_type = post_form.cleaned_data['excerpt_type']
# Removed tags=tags from the below line
# Also, if you want to use `save` then you don't want to use
# `create` as it will persist into your db right away.
# Simply create an instance of Blog
ins = Blog(user=request.user, content=content, title=title,
image=image, context=context,
excerpt_type=excerpt_type)
# Adding tags against the object field after the object creation
for tag in tags:
ins.tags.add(tag)
ins.save()
messages.success(request, 'Your Post has been successfully posted')
print(request.POST)
print(tags)
return HttpResponseRedirect(reverse('post_upload'))
else:
print(f'error in {request.POST}')
else:
post_form = PostUpload(instance=request.user)
context = {'post_form': post_form, 'index1': index1}
return render(request, 'post_upload.html', context)
Upvotes: 2
Reputation: 90
Inside post_upload
method, are you sure you need instance=request.user
to create a post_form
object?
Upvotes: 0
Reputation: 485
You have to call form.save_m2m() to save tags when using django-taggit library like this:
post_form = PostUpload(request.POST, request.FILES, instance=request.user)
if post_form.is_valid():
obj = post_form.save(commit=False)
obj.save()
# Without this next line the tags won't be saved.
post_form.save_m2m()
messages.success(request, 'Your Post has been successfully posted')
print(request.POST)
print(tags)
return HttpResponseRedirect(reverse('post_upload'))
You can read more here.
Upvotes: 0