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

在同一模板中结合使用CreateView与ListView,解决UserAppointment表单提交失效及外键自动赋值问题

问题解决指南:Django模板中同时使用CreateView和ListView,表单提交失败及自动赋值问题

一、修复表单提交无响应问题

你的模板里缺少<form>标签,这是提交按钮没反应的核心原因。提交按钮必须包裹在<form>标签内,同时要包含Django的CSRF令牌以防止跨站请求伪造。

修改你的HTML模板:

<div class="container">
    <!-- 添加form标签,指定POST方法 -->
    <form method="POST">
        {% csrf_token %}
        {% for appointment in object_list %}
        <tbody>
            <tr class="inner-box">
                <th scope="row">
                    <div class="event-date">
                        {{ appointment.date_work }}
                    </div>
                </th>
                <td>
                    <div class="event-img">
                        {% if appointment.id_image %}
                        <img src="#" alt="">
                        {% endif %}
                        <p>{{ appointment.event.name }}</p>
                    </div>
                </td>
                <td>
                    <div class="event-wrap">
                        <h3><a href="#">{{ appointment.shift }}</a></h3>
                        <div class="time">
                            <!-- 隐藏字段:传递当前StaffDuty和Event的ID -->
                            <input type="hidden" name="staff" value="{{ appointment.id }}">
                            <input type="hidden" name="event" value="{{ appointment.event.id }}">
                            <!-- 只显示需要用户填写的字段 -->
                            <span>{{ form.morning_hour }}</span>
                            <span>{{ form.afternoon_hour }}</span>
                        </div>
                    </div>
                </td>
                <td>
                    <div class="r-no">
                        <span> {{ appointment.spots_free|default:"0" }}/{{ appointment.event.spots_total }}</span>
                    </div>
                </td>
                <td>
                    <div class="r-no">
                        <span>{{ appointment.event.venue }}</span>
                    </div>
                </td>
                <td>
                    <div class="primary-btn">
                        <input type="submit" value="提交预约" class="btn btn-primary">
                    </div>
                </td>
            </tr>
        </tbody>
        {% endfor %}
    </form>
</div>

关键修改点:

  • 新增<form method="POST">和{% csrf_token %},确保表单能正常提交
  • 把staff和event改为隐藏输入框,传递当前StaffDuty的ID,用于后续自动赋值
  • 修正显示逻辑,只保留用户需要手动填写的时段字段

二、修复UserAppointmentAddView的自动赋值逻辑

你的视图存在多处逻辑错误,比如获取关联对象的方式不正确,字段填充代码缺失。修改后的视图如下:

class UserAppointmentAddView(CreateView):
    model = UserAppointment
    form_class = UserAppointmentForm
    template_name = "reservation.html"
    success_url = reverse_lazy('home')

    def form_valid(self, form):
        # 1. 赋值当前登录用户的UserProfile实例
        form.instance.user = self.request.user.userinformation

        # 2. 从POST数据中获取用户选中的StaffDuty
        staff_id = self.request.POST.get('staff')
        if staff_id:
            selected_staff = StaffDuty.objects.get(id=staff_id)
            form.instance.staff = selected_staff
            
            # 3. 从StaffDuty自动填充date_appointment
            form.instance.date_appointment = selected_staff.date_work
            
            # 4. 从StaffDuty关联的Event填充event和event_name
            form.instance.event = selected_staff.event
            form.instance.event_name = selected_staff.event.name

        # 可选:自动计算剩余名额(如果需要)
        # form.instance.spots_free = form.instance.event.spots_total - UserAppointment.objects.filter(event=form.instance.event).count()

        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        # 只显示当前用户的StaffDuty列表(避免展示其他用户的职责)
        kwargs['object_list'] = StaffDuty.objects.filter(user=self.request.user.userinformation).order_by('id')
        return super().get_context_data(**kwargs)

关键修正点:

  • 通过self.request.POST.get('staff')获取用户选中的StaffDuty(来自模板的隐藏字段)
  • 基于选中的StaffDuty自动填充date_appointment、event和event_name
  • 过滤当前用户的StaffDuty数据,确保用户只能看到自己的职责

三、调整UserAppointmentForm表单

为了让自动赋值的字段不显示在表单中,需要在表单类中指定仅显示用户需要输入的字段:

# forms.py
from django import forms
from .models import UserAppointment

class UserAppointmentForm(forms.ModelForm):
    class Meta:
        model = UserAppointment
        # 只保留需要用户手动填写的字段
        fields = ['morning_hour', 'afternoon_hour']

这样表单只会渲染时段输入框,其他字段通过视图自动赋值,避免用户误操作。

四、其他细节修正

  1. 修复StaffDuty模型的__str__方法(原代码的|是语法错误):
def __str__(self):
    return f"{self.event.name} {self.date_work}"
  1. 修复UserAppointment模型的__str__方法:
def __str__(self):
    return f"{self.event.name} {self.staff.date_work}"
  1. 确保UserProfile与User是一对一关联:
# models.py中UserProfile的定义
class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # 其他字段...

这样self.request.user.userinformation才能正确获取当前用户的UserProfile实例。

通过以上步骤,你的表单应该可以正常提交,并且自动填充所有所需的外键和字段值了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 22:42:34