簡體   English   中英

Django form.is_valid() 返回 False

[英]Django form.is_valid() returns False

我正在 Django 中創建一個博客,我一直堅持添加 post_update_view,其中form.is_valid() 返回 False並且我無法更新帖子。

我也檢查過這個,但我無法導航到正確的位置。

此外,這很奇怪,因為創建后form.is_valid()工作正常(我在那里分配“ form = PostModelForm(request.POST or None) ”)。

我將不勝感激任何建議。

下邊是:

視圖.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)

模型.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

表格.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

模板

{% 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 %}

網址

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),
]

評論太長了,我不確定這是否能解決問題,但是 bruno desthuillers 已經鏈接到“視圖應該是什么樣子”。 需要注意的重要一點是,未綁定表單(通過 HTTP GET 訪問的 URL)有一個代碼路徑,通過 HTTP POST 從瀏覽器提交的數據有一個不同的代碼路徑。

我一直討厭規范表單將驗證表單數據的處理與雙方的樣板夾在中間的方式,並建議否定有效性測試,並使用一點 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")

如果這不是答案,請將您的模板替換為最簡單的{{ form.as_p }}和一個提交按鈕,看看是否能解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM