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()]): # 保存逻辑
额外优化建议
- 模板按钮文字改为中文,提升体验:
<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"/>
- 修正
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
相关产品推荐
相关产品推荐

