简体   繁体   English

Django form.is_valid() 返回 False

[英]Django form.is_valid() returns False

I am creating a blog in Django and I'm stuck at adding writing post_update_view, where form.is_valid() returns False and I'm not able to update the post.我正在 Django 中创建一个博客,我一直坚持添加 post_update_view,其中form.is_valid() 返回 False并且我无法更新帖子。

I've also checked this but I could not navigate to the right spot.我也检查过这个,但我无法导航到正确的位置。

Also, it's weird as for post creation form.is_valid() works fine (I'm assigning " form = PostModelForm(request.POST or None) " there).此外,这很奇怪,因为创建后form.is_valid()工作正常(我在那里分配“ form = PostModelForm(request.POST or None) ”)。

I would appreciate any suggestions.我将不胜感激任何建议。

Below is:下边是:

Views.py视图.py

def post_update_view(request, slug):
    obj = get_object_or_404(Post, slug=slug)
    form = PostModelForm(request.POST or None, instance=obj)
    print(form.is_valid())
    if form.is_valid():
        form.save()
    template_name = 'blog/post_update.html'
    context = {'form': form, 'title': f'Update {obj.title}'}
    return render(request, template_name, context)

models.py:模型.py:

from django.conf import settings
from django.db import models

User = settings.AUTH_USER_MODEL

class Post(models.Model):
    CATEGORY_CHOICES = (
        (None, '--------'),
        ('CB', 'City Break'),
        ('1W', 'Week holidays'),
        ('2W', 'Two weeks holidays'),
        ('MO', 'Month holidays'),
        ('SB', 'Sabbatical'),
    )

    CONTINENT_CHOICES = (
        (None, '--------'),
        ('AS', 'Asia'),
        ('AU', 'Australia and Oceania'),
        ('AF', 'Africa'),
        ('EU', 'Europe'),
        ('NA', 'North America'),
        ('SA', 'South America'),
    )

    user = models.ForeignKey(
        User,
        default=1,
        null=True,
        on_delete=models.SET_NULL
    )
    title = models.CharField(max_length=150)
    date = models.DateField()
    category = models.CharField(
        max_length=100,
        choices=CATEGORY_CHOICES,
        blank=True
    )
    continent = models.CharField(
        max_length=100,
        choices=CONTINENT_CHOICES,
        blank=True
    )
    body = models.TextField()
    slug = models.SlugField()

    def __str__(self):
        return self.slug

forms.py:表格.py:

from django import forms
from blog.models import Post


class PostModelForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'date', 'category', 'continent', 'slug', 'body']

    def clean_slug(self):
        instance = self.instance
        slug = self.cleaned_data.get('slug')
        qs = Post.objects.filter(slug__iexact=slug)
        qs_title_id = 0
        if instance is not None:
            qs = qs.exclude(pk=instance.pk)
        if qs.exists():
            raise forms.ValidationError(f"Slug has already been used in "
                                        f"'{qs[qs_title_id]}'.\n Please "
                                        f"change.")
        return slug

templates模板

{% extends "site_general/header.html" %}

{% block content %}
    {% if title %}
        <h1>{{ title }}</h1>
    {% endif %}

    <form method="POST" action="."> {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Update</button>
    </form>

{% endblock %}

urls网址

from django.urls import path
from .views import (
    post_delete_view,
    post_detail_view,
    post_list_view,
    post_update_view,
)

urlpatterns = [
    path('', post_list_view),
    path('<str:slug>/', post_detail_view),
    path('<str:slug>/edit', post_update_view),
    path('<str:slug>/delete', post_delete_view),
]

Too long for a comment, and I'm not sure whether this will solve the problem, but bruno desthuillers has linked to "what a view should look like".评论太长了,我不确定这是否能解决问题,但是 bruno desthuillers 已经链接到“视图应该是什么样子”。 The important thing to note is that there is one code path for an unbound form (URL accessed via HTTP GET) and a different one for data submitted from the browser by HTTP POST.需要注意的重要一点是,未绑定表单(通过 HTTP GET 访问的 URL)有一个代码路径,通过 HTTP POST 从浏览器提交的数据有一个不同的代码路径。

I have always detested the way that canonical form sandwiches the processing of validated form data with boilerplate on both sides, and would suggest negating the validity test, and using a little Python magic to combine the form instantiation for both GET and POST cases:我一直讨厌规范表单将验证表单数据的处理与双方的样板夹在中间的方式,并建议否定有效性测试,并使用一点 Python 魔法来组合 GET 和 POST 案例的表单实例化:

def post_update_view(request, slug):
    obj = get_object_or_404(Post, slug=slug)
    args = [request.POST] if request.method == "POST" else []
    form = PostModelForm(*args, instance=obj)
    if request.method != "POST" or not form.is_valid(): 
        # GET or not valid 
        context = {'form': form, 'title': f'Update {obj.title}'}
        return render(request, 'blog/post_update.html', context)

    # the form validated, do the work and redirect
    form.save()
    return redirect("wherever you want, but redirect")

If this isn't the answer, replace your template with the simplest possible {{ form.as_p }} and a submit button, and see whether that fixes it.如果这不是答案,请将您的模板替换为最简单的{{ form.as_p }}和一个提交按钮,看看是否能解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM