【问题标题】:How to update a django formset?如何更新 django 表单集?
【发布时间】:2021-01-06 13:41:13
【问题描述】:

我是 Django 和 Web 开发的新手。我正在使用表单集将数据保存到数据库中。创建部分工作正常,但是当我尝试使用表单集更新数据库中的现有数据时遇到问题。

以下是相关代码sn-ps:

型号:

from django.db import models

class GradingSchemeName(models.Model):
    name = models.CharField(max_length=250, null=False, blank=False, unique=True)

class GradingScheme(models.Model):
    scheme_name = models.ForeignKey(to=GradingSchemeName, on_delete=models.CASCADE)
    grade = models.CharField(max_length=250, null=False, blank=False)
    score_range_begin = models.SmallIntegerField()
    score_range_end = models.SmallIntegerField()

    class Meta:
        unique_together = ('scheme_name', 'grade',)

表格:

from django.forms import ModelForm, inlineformset_factory

GradeFormSet = inlineformset_factory(
    parent_model=GradingSchemeName, model=GradingScheme,
    fields=['scheme_name', 'grade', 'score_range_begin', 'score_range_end'],
    extra=10, max_num=100, can_delete=False
)

观看次数:

# Passing the pre-filled form for rendering. For the sake of illustration, I have hardcoded the `id=1`:
instance = GradingSchemeName.objects.get(id='1')        
context['grade_formset'] = GradeFormSet(instance=instance)

# checking the request data from the post(request) on form submission:
grades_formset = GradeFormSet(request.POST, instance=instance)

请注意,在创建表单集期间,GradingScheme 模型中保存了 3 条记录。当我尝试使用上述方法进行更新时,我看到 grades_formset 有 13 条记录(3 条来自 instance 属性,10 条来自额外表单)。该问题是在执行is_valid() 方法时引起的:

if not grades_formset.is_valid():
    messages.error(request, 'Form data is invalid!')

is_valid() 方法对 3 条记录中的每一条都抛出以下错误:

  • id : 此字段为必填项
  • “errorlist nonfield”:具有此方案名称和等级的评分方案已存在。

不确定,如何解决上述两个错误。任何指针都会非常有帮助。提前致谢。

【问题讨论】:

    标签: python django formset


    【解决方案1】:

    我喜欢基于类的视图,所以这可能是我对您的问题的解决方案:

    from django.db import transaction
    
    class GradeUpdateView(UpdateView):
        template_name = 'Your Template'
        form_class = yourtemplateForm
        model = GradingSchemeName
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
    
            if self.request.method == 'POST':
                context['formset'] = GradeFormSet(self.request.POST, instance=self.object)
            else:
                context['formset'] = GradeFormSet(instance=self.object)
    
            return context
    
        def form_valid(self, form):
            context = self.get_context_data()
            formset = context['formset']
    
            with transaction.atomic():
                self.object = form.save()
    
                if formset.is_valid():
                    formset.instance = self.object
                    formset.save()
    
            return redirect('your url')
    

    【讨论】:

    • 我不确定,如何使用form_class,我会检查一下。顺便说一句,我也在使用 CBV,但是,视图代码太大,无法在 StackOverflow 中显示。这是 View 的完整实现的链接 - codeshare.io/GLd0JK。欢迎您的 cmets!
    • 为什么要用scheme_name_id,在验证的时候才知道属于哪个方法?
    • with self.object 足以知道您要修改哪个对象
    • 您的 GradingSchemeNameForm 进入 form_class,这样效果更好,无需选择类中的字段
    • 感谢您的反馈。我正在使用scheme_name_id 来确定要更新哪个GradingScheme。我的模板 (codeshare.io/5Q300W) 有两种形式。第一种形式设置scheme_name_id,基于此选择,我将值填充到第二种形式中。第二种形式是GradeFormSet
    猜你喜欢
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 2012-03-06
    相关资源
    最近更新 更多