Search code examples
djangodjango-modelsdjango-viewsdjango-forms

Why isn't my Django form sending data to the database?


I'm new to Django and Python. I created a blog for my project but when trying to use a form to add blog posts to the database I can't figure out how to make the send button to actually update the model in the database. I managed to make it show in the view but the send button is the problem.

This is the model:

class BlogPost(models.Model):
    title = models.CharField(max_length=250)
    content = models.TextField()
    post_author = models.CharField(max_length=30)
    creation_date = models.DateTimeField(auto_now_add=True)
    modification_date = models.DateTimeField(auto_now=True)
    image = models.ImageField(upload_to='blog/files/blog_images')
    categories = models.ManyToManyField('Category', related_name='posts') #Relaciona el atributo con la clase Category y permite usar category.posts

    def __str__(self):
        return self.title
    
    class Meta:
        verbose_name = "blog post"
        verbose_name_plural = "blog posts"

This is the form:

class newPostForm(forms.Form):
    title = forms.CharField(max_length=250)
    content = forms.CharField(
        widget=forms.Textarea()
    )
    image = forms.ImageField()
    post_author = forms.CharField()

This is the view:

def new_post(request):
    if request.method == "POST":
        form = newPostForm(request.POST)
        if form.is_valid():
            
            info = form.cleaned_data()

            new_post_info = BlogPost(
                title=info["title"],
                content=info["content"],
                image=info["image"],
                post_author=info["post_author"],
                )

            new_post_info.save()    

            return render(request, "")
        
    else:
        form = newPostForm()
    
    return render(request, "blog/new_post.html", {"form":form})

I don't know if you need any more information, let me know. Thanks in advance!


Solution

  • Your form contains an ImageField, this means it needs access to request.FILES as well:

    from django.shortcuts import redirect
    
    
    def new_post(request):
        if request.method == 'POST':
            form = newPostForm(request.POST, request.FILES)
            if form.is_valid():
                info = form.cleaned_data
                new_post_info = BlogPost(
                    title=info['title'],
                    content=info['content'],
                    image=info['image'],
                    post_author=info['post_author'],
                )
                new_post_info.save()
                return redirect('name-of-some-form')
        else:
            form = newPostForm()
        return render(request, 'blog/new_post.html', {'form': form})

    and encode the files in the form data by specifying enctype="" in the HTML form:

    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <!-- … -->
    </form>

    I would however strongly advise to work with a ModelForm, that will handle the form and saving it automatically:

    class PostForm(forms.ModelForm):
        class Meta:
            model = BlogPost
            fiels = ['title', 'content', 'image', 'post_author']

    then we work with:

    from django.shortcuts import redirect
    
    
    def new_post(request):
        if request.method == 'POST':
            form = PostForm(request.POST, request.FILES)
            if form.is_valid():
                form.save()
                return redirect('name-of-some-view')
        else:
            form = PostForm()
        return render(request, 'blog/new_post.html', {'form': form})

    Note: In case of a successful POST request, you should make a redirect [Django-doc] to implement the Post/Redirect/Get pattern [wiki]. This avoids that you make the same POST request when the user refreshes the browser.