Search code examples
djangodjango-modelsdjango-viewsdjango-formsdjango-taggit

Tags are not being stored in the database even after saving form in django


views.py

def post(request):
    if request.method == 'POST':
        form = PostModelForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.save()
            # using the for loop i am able to save the tags data.
            # for tag in form.cleaned_data['tags']:
            #    post.tags.add(tag)
            images = request.FILES.getlist('images')
            for image in images:
                ImagesPostModel.objects.create(post=post, images=image)
        return redirect('/Blog/home/')
    else:
        form = PostModelForm(request.POST)
        return render(request, 'post.html', {'form': form})

models.py

class PostModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date_time = models.DateTimeField(auto_now_add=True)
    title = models.TextField(null=True)
    body = models.TextField(null=True)
    tags = TaggableManager()
    def __str__(self):
        return str(self.user)

post.html

{% extends 'base.html' %}

{% block content %}

<form action="{% url 'post' %}" enctype="multipart/form-data" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="file" multiple name="images">
    <input type="submit">
</form>

{% endblock %}

After giving the input the data is stored in the tags field but, not saving in the database. I can manually insert data through the admin panel successfully but not as a non-staff user. I have installed taggit and placed it in the installed_apps in settings.py. Tags are being saved using post.tags.add(tag) inside for loop. What is the issue with the code?


Solution

  • This is because you use commit=False for the form: then the form has no means to save the many-to-many fields. It is also not necessary to do that, you can work with:

    def post(request):
        if request.method == 'POST':
            form = PostModelForm(request.POST)
            if form.is_valid():
                form.instance.user = request.user  # set the user
                post = form.save()  # save the form
                ImagesPostModel.objects.bulk_create([
                    ImagesPostModel(post=post, images=image)
                    for image in request.FILES.getlist('images')
                ])
            return redirect('/Blog/home/')
        else:
            form = PostModelForm()
        return render(request, 'post.html', {'form': form})

    Note: Models normally have no Model suffix. Therefore it might be better to rename PostModel to Post.


    Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.