You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Crispy表单提交后数据无法保存及渲染问题求助

如何保存Django Crispy表单中的数据?

问题描述

点击表单提交按钮后,进入帖子渲染页面却看不到刚创建的帖子。表单样式如下:
表单样式

相关代码

表单页面:anzeige_new.html

{% load crispy_forms_tags %}
{% block content %}
      <div class="content-section">
          <form method="POST">
              {% csrf_token %}
              <fieldset class="form-group">
                  <legend class="border-bottom mb-4">创建广告</legend>
                  {{ form|crispy }}
              </fieldset>
              <div class="form-group">
                  <button class="btn btn-outline-info" type="submit">发布</button>
              </div>
          </form>
      </div>
{% endblock content %}

帖子渲染页面(初始版本):angebote.html

{% block content %}
{% for post in posts %}
  <p>进入循环</p>
  <a class="mr-2" href="#">{{ Post.objects.all }}</a>
  <article class="media content-section">
    <img class="rounded-circle article-img" src="{{ post.author.profile.image.url">
    <div class="media-body">
      <div class="article-metadata">
        <a class="mr-2" href="#">{{ post.author }}</a>
        <small class="text-muted">{{ post.date_posted|date:"F d, Y" }}</small>
      </div>
      <h2><a class="article-title">{{ post.title }}</a></h2>
      <p class="article-content">{{ post.content }}</p>
    </div>
  </article>
{% endfor %}
{% endblock content %}

forms.py

class PostForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)

        # 给表单实例传入FormHelper,自动生成默认布局
        self.helper = FormHelper(self)

        # 动态添加提交按钮
        self.helper.layout.append(Submit('save', 'save'))

    class Meta:
        model = Post
        fields = ('title', 'category', 'weekday')

models.py

class Post(models.Model):
    title = models.CharField(max_length=100)
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
    post = models.CharField(max_length=100, default='SOME STRING')


    weekday_choices = (
        ('Monday', 'Monday'),
        ('Tuesday', 'Tuesday'),
        ('Wednesday', 'Wednesday'),
        ('Thursday', 'Thursday'),
        ('Friday', 'Friday'),
        ('Saturday', 'Saturday'),
        ('Sunday', 'Sunday'),
    )

    weekday = models.CharField(max_length=15, choices=weekday_choices, default=0)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('post-detail', kwargs={'pk': self.pk})

views.py(初始版本)

class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    fields = ['title', 'category', 'weekday']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)


class PostListView(ListView):
    model = Post
    template_name = 'vereinsapp/angebote.html'  # <app>/<model>_<viewtype>.html
    context_object_name = 'posts'
    ordering = ['-date_posted']  # 帖子按最新到最旧排序


class CreateView(TemplateView):
    template_name = 'vereinsapp/anzeige_new.html'
    print("Inside Create View")
    def post(self, request):
        form = PostForm(request.POST)
        if form.is_valid():
            text = form.cleaned_data['post']
            post = form.save()
            post.save()
            form = PostForm()
            post = form.save()
            return redirect('post:posts')

        args = {'form': form}
        return render(request, self.template_name, args)

urls.py

urlpatterns = [
    path('', views.index, name='index'),
    path('vereinsapp/', views.index, name='index'),
    path('angebote/', views.angebote),
    path('angebotsprofil/', views.angebotsprofil),
    path('vereinsmarketing/', views.vereinsmarketing),
    path('anzeige_new/', views.anzeige_new),
    path('nutzerprofil/', views.nutzerprofil),

    path('posts/', PostListView.as_view(), name='posts'),
    path('post/new/', PostCreateView.as_view(), name='post-create'),
    path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
    path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
    path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
]

更新后的代码

PostListView(views.py)

class PostListView(ListView):
    model = Post
    template_name = 'vereinsapp/angebote.html'  # <app>/<model>_<viewtype>.html
    context_object_name = 'posts'
    ordering = ['-date_posted']  # 帖子按最新到最旧排序
    queryset = Post.objects.all()

帖子渲染页面(更新后):angebote.html

{% block content %}
{% for post in posts %}
  <p>进入循环</p>
  <a class="mr-2" href="#">{{ post }}</a>
  <article class="media content-section">
    <img class="rounded-circle article-img" src="{{ post.author.profile.image.url">
    <div class="media-body">
      <div class="article-metadata">
        <a class="mr-2" href="#">{{ post.author }}</a>
        <small class="text-muted">{{ post.weekday }}</small>
      </div>
      <h2><a class="article-title">{{ post.title }}</a></h2>
      <p class="article-content">{{ post.category }}</p>
    </div>
  </article>
{% endfor %}
{% endblock content %}

问题排查与解决

核心问题1:表单提交路径不匹配

你的表单页面anzeige_new.html对应的URL是anzeige_new/,绑定的视图是views.anzeige_new,但自定义的CreateView并未被使用。真正处理创建逻辑的PostCreateView对应URL是post/new/,这意味着当前提交的表单根本没走正确的创建视图,数据自然不会保存。

解决:

  • 要么修改表单的action属性,指向正确的创建视图:
    <form method="POST" action="{% url 'post-create' %}">
    
  • 要么将urls.py中anzeige_new/的视图改为自定义CreateView(更推荐用Django自带的PostCreateView)。

核心问题2:自定义CreateView逻辑错误

自定义CreateView有多处问题:

  1. 尝试获取form.cleaned_data['post'],但PostForm并未包含post字段(表单字段是title、category、weekday),会直接抛出KeyError。
  2. 保存表单后重新实例化空表单并再次保存,相当于创建了一个空Post对象,完全多余。
  3. 重定向的'post:posts'命名空间不存在,URL中posts的name是'posts',应改为redirect('posts')。

如果要使用自定义视图,修正后代码如下:

class CreateView(TemplateView):
    template_name = 'vereinsapp/anzeige_new.html'

    def get(self, request):
        form = PostForm()
        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = PostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)  # 先不保存到数据库
            post.author = request.user  # 手动设置作者
            post.save()  # 保存到数据库
            return redirect('posts')

        return render(request, self.template_name, {'form': form})

核心问题3:模型与模板字段不匹配

  • Post模型中没有category字段,但表单和模板都用到了该字段,会导致表单验证失败或模板渲染错误。需在models.py中添加:
    category = models.CharField(max_length=100)  # 可根据需求调整字段类型和参数
    
  • 模板中{{ post.author.profile.image.url }}缺少闭合的}},修正为:{{ post.author.profile.image.url }}

其他问题

  • Post模型中weekday的default=0错误,选项是字符串类型(如'Monday'),应设置默认值为选项中的一个,比如default='Monday'。
  • PostListView里的queryset = Post.objects.all()多余,model = Post已默认获取所有对象。

总结修正步骤

  1. 在models.py中添加category字段,修正weekday的默认值。
  2. 确保表单提交到正确的视图(使用PostCreateView或修正自定义CreateView)。
  3. 修正模板中的语法错误和字段匹配问题。
  4. 检查视图中的重定向和表单处理逻辑,确保数据正确保存到数据库。

内容的提问来源于stack exchange,提问作者mx1txm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:55:15