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

Django中BooleanField无法保存至PostgreSQL数据库问题求助

问题描述

我试了好几种视图保存方式,都没法把BooleanField保存到PostgreSQL数据库里,但inlineformset的保存完全正常。下面是我写的最简代码,另外用all()包裹验证代码时会报‘bool不可迭代’的类型错误,我知道肯定漏了细节,但找不到问题在哪。


模型代码

class SundayBoolAvailable(models.Model):
    teacher_id = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True,
                                   default='',
                                   related_name='teacher_bool_available_id')
    sunday_bool = models.BooleanField(null=False, default=True)


class SundayTime(models.Model):
    teacher_id_time = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True,
                                        default='',
                                        related_name='teacher_time_available_id')
    sun_from_hour = models.TimeField(choices=HOUR_CHOICES, null=True, blank=True)
    sun_to_hour = models.TimeField(choices=HOUR_CHOICES, null=True, blank=True)

    def __str__(self):
        return str(self.teacher_id)

视图代码

@login_required()
@teacher_required
def availability_update_view(request, pk, *args, **kwargs):
    sun_obj = get_object_or_404(MyUser, id=pk)
    if request.method == 'POST':
        sun_bool = SundayBoolForm(request.POST, request.FILES, instance=sun_obj)
        sunday_formset = SundayInlineFormSet(request.POST, request.FILES, instance=sun_obj, prefix='id_sunday_formset')
        if sun_bool.is_valid() and sunday_formset.is_valid():
            sun_bool.save(commit=False)
            sunday_formset.save()
            messages.success(request, f'You have successfully updated your availability!')
            return redirect('teacher_profile')

    else:
        sun_bool = SundayBoolForm(instance=sun_obj)
        sunday_formset = SundayInlineFormSet(instance=sun_obj, prefix='id_sunday_formset')

    context = {
        'sun_bool': sun_bool, 'sunday_formset': sunday_formset
    }

    return render(request, 'appointment/availability_update_new.html', context)

表单代码

class SundayBoolForm(forms.ModelForm):
    #    sunday_bool = forms.BooleanField(required=False)

    class Meta:
        model = SundayBoolAvailable
        fields = ['sunday_bool']

    #        widgets = {
    #            'sunday': forms.HiddenInput(),
    #        }
    def __init__(self, *args, **kwargs):
        super(SundayBoolForm, self).__init__(*args, **kwargs)
        self.fields['sunday_bool'].required = False


class SundayTimeForm(forms.ModelForm):
    class Meta:
        model = SundayTime
        fields = ['sun_to_hour', 'sun_from_hour']


#        widgets = {
#            'sunday': forms.HiddenInput(),
#        }

SundayInlineFormSet = inlineformset_factory(MyUser, SundayTime, form=SundayTimeForm, extra=0,
                                            can_delete=True, min_num=0, validate_min=True, max_num=3, validate_max=True,
                                            fields=['sun_to_hour', 'sun_from_hour'])

模板代码

{% load crispy_forms_tags %}
{% load static %}
{% block content %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>

        <link rel="stylesheet" type="text/css" href="{% static 'css/availability_update_new.css' %}">
    </head>
    <body>
    <input type="button" class="sun-not-available" value="Not Available Sunday" onclick="sunCheckOne(); sunHideShow()"
           id="sun-not-available">
    <form id="all-add-form" method="POST" action="" enctype="multipart/form-data">
        <div class="sunday-all" id="sunday-all-id">
            {% csrf_token %}
            <legend class="bottom mb-4">Profiles Info</legend>
            <div class="sun-bool">
                {{ sun_bool.sunday_bool }}
            </div>
        </div>
        {{ sunday_formset.management_form }}
        {% for sun_form in sunday_formset %}
            {% for hidden in sun_form.hidden_fields %}
                {{ hidden }}
            {% endfor %}
            <div class="sun_time_slot_form">
                {{ sun_form }}
                <button class="delete-sun-form" type="button" id="delete-sun-btn" onclick=""> Delete This
                    Sunday
                    Timeslot
                </button>
            </div>
        {% endfor %}
        <button id="add-sun-form" type="button" class="button">Add Other Sunday Times</button>
        <input type="submit" name="submit" value="Submit" class="btn btn-primary"/>
    </form>
    <script type="text/javascript" src="{% static 'js/add_timeslot.js' %}"></script>
    </body>
    </html>
{% endblock %}

问题分析与解决

1. BooleanField无法保存的核心原因

你初始化SundayBoolForm时传入的instance是MyUser对象,但SundayBoolForm关联的模型是SundayBoolAvailable,两者不匹配,导致表单无法正确绑定到用户对应的SundayBoolAvailable实例,自然无法保存数据。

修复代码

修改视图中表单的初始化逻辑,先获取/创建当前用户对应的SundayBoolAvailable实例:

@login_required()
@teacher_required
def availability_update_view(request, pk, *args, **kwargs):
    sun_obj = get_object_or_404(MyUser, id=pk)
    # 获取或创建当前用户的SundayBoolAvailable实例
    sun_bool_instance, created = SundayBoolAvailable.objects.get_or_create(teacher_id=sun_obj)
    
    if request.method == 'POST':
        # 传入正确的关联实例
        sun_bool = SundayBoolForm(request.POST, instance=sun_bool_instance)
        sunday_formset = SundayInlineFormSet(request.POST, instance=sun_obj, prefix='id_sunday_formset')
        
        if sun_bool.is_valid() and sunday_formset.is_valid():
            # 直接保存,不需要commit=False
            sun_bool.save()
            sunday_formset.save()
            messages.success(request, f'您已成功更新可用时间!')
            return redirect('teacher_profile')

    else:
        sun_bool = SundayBoolForm(instance=sun_bool_instance)
        sunday_formset = SundayInlineFormSet(instance=sun_obj, prefix='id_sunday_formset')

    context = {
        'sun_bool': sun_bool, 'sunday_formset': sunday_formset
    }

    return render(request, 'appointment/availability_update_new.html', context)

2. ‘bool不可迭代’错误原因

all()函数需要接收可迭代对象(比如列表、元组),如果你写成all(sun_bool.is_valid() and sunday_formset.is_valid()),就会把一个布尔值传给all(),导致报错。正确写法应该是:

if all([sun_bool.is_valid(), sunday_formset.is_valid()]):
    # 保存逻辑

额外优化建议

  1. 模板按钮文字改为中文,提升体验:
<input type="button" class="sun-not-available" value="周日不可用" onclick="sunCheckOne(); sunHideShow()" id="sun-not-available">
<button class="delete-sun-form" type="button" id="delete-sun-btn" onclick=""> 删除该周日时段</button>
<button id="add-sun-form" type="button" class="button">添加其他周日时段</button>
<input type="submit" name="submit" value="提交" class="btn btn-primary"/>
  1. 修正SundayBoolAvailable模型中外键的不合理默认值:
teacher_id = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True,
                               related_name='teacher_bool_available_id')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:15:02