自定义表单集:分配外键值并只输入一次字段[登录用户]

2024-05-18 06:11:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个modelformset来填充时间表模型

型号

class Timetable(models.Model):
    day = models.ForeignKey('Day',on_delete=models.CASCADE)
    start = models.IntegerField()
    end = models.IntegerField()
    period = models.CharField(max_length=12)
    classteacher = models.ForeignKey('Class_teacher',on_delete=models.SET_NULL)

class Class_teacher(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    empid = models.CharField(max_length=10)
    email = models.CharField(max_length=30)

视图

class Timetableadding(CreateView):
    model =  Timetable
    success_url = '/dashboard'
    form_class = Timetableform
    template_name = 'newtest.html'

    def get_context_data(self, **kwargs):
        context = super(Timetableadding, self).get_context_data(**kwargs)
        context['formset'] = TimetableFormSet(queryset=Timetable.objects.none())
        return context

    def post(self, request, *args, **kwargs):
        formset = TimetableFormSet(request.POST)
        if formset.is_valid():
            return self.form_valid(formset)

    def form_valid(self, formset):
        formset.classteacher = get_object_or_404(Class_teacher, email=self.request.user.email)
        formset.save()
        # return super().form_valid(formset)
        return HttpResponseRedirect('/dashboard')

表格

class Timetableform(ModelForm):
    class Meta:
        model = Timetable
        fields = ( 'start', 'end', 'period')

TimetableFormSet = modelformset_factory(Timetable, fields=('start', 'end', 'period'),extra=8,)

模板

<form class="form-material m-t-40 floating-labels" method="post" enctype="multipart/form-data">
     {% csrf_token %}
     {{ formset.management_form }}
     {% for form in formset %}
          {{ form }}<br><br>
     {% endfor %}
     <div class="form-group row">
          <button type="submit" class="btn waves-effect waves-light btn-rounded btn-success">
                Submit
          </button>

      </div>
</form>

当使用createview视图填充Timetableform时,Timetable模型中的字段start end period就像一般形式一样完成

要求

  1. webapp具有登录功能。当用户(班主任)登录时,他们可以添加时间表。我想要的是时间表(模型表单)中的classteacher字段应该自动设置为user,即classteacher并应在创建时间表后保存在数据库中。Classteacher模型用相应的必填字段更新

我试着把班主任传给表格组,但我需要的话就执行了

I know how to do within a normal form , But I have not done this in a formset.

  1. Timetable中的day字段只应选择一次,因此将有8个表单提供startendperiod,但应该只有一个表单提供day。我成功地为startendperiod处理了8个表单,但不知道day

Tags: 模型selfformmodelscontext时间表startlength
2条回答

有更好的方法:

  • 如果使用inlineformset_factory,则可以在初始化表单集时直接传递表单集所属的教师实例。参见示例here
  • 或者可以在表单中循环,以便在保存实例之前对其进行修改:

    instances = formset.save(commit=False)
    for instance in instances: 
        instance.classteacher = ...
        instance.save()
    

如果希望用户提交所有实例共用的额外字段,可以向视图中添加其他窗体:

class DayForm(forms.Form):
    day = ModelChoiceField(queryset=Day.objects.all())

def get_context_data(self, **kwargs):
    ...
    context['day_form'] = DayForm()
    return context

def post(self, *args, **kwargs):
    ...
    day_form = DayForm(data=request.POST)
    if formset.is_valid() and day_form.is_valid():
        return self.form_valid(formset, day_form)

def form_valid(self, formset, day_form):
    day = day_form.cleaned_data['day']
    instances = formset.save(commit=False)
    for instance in instances:
        instance.day = day
        instance.teacher = ...
        instance.save()
    return HttpResponseRedirect(...)

要渲染的模板

<form class="form-material m-t-40 floating-labels" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ day_form }} <br>
{{ formset.management_form }}
{% for form in formset %}
     {{ form }}<br><br>
{% endfor %}
     <div class="form-group row">
          <button type="submit" class="btn waves-effect waves-light btn-rounded btn-success">
    Submit
          </button>

     </div>
</form>

在CreateView中,可以重写get\u initial方法:

def get_initial(self):
    self.initial = CreateView.get_initial(self)
    self.initial["classteacher"] = self.request.user
return self.initial.copy()

然后需要将此字段添加到表单中

class Timetableform(ModelForm):
    class Meta:
        model = Timetable
        fields = ( 'start', 'end', 'period', “classteacher”)


如果您不想在窗体中显示此字段,并且仍然将classteacher添加为当前用户,则可以将HiddeInput小部件用于此字段:

class Timetableform(ModelForm):
    class Meta:
        model = Timetable
        fields = ( 'start', 'end', 'period', “classteacher”)
           widgets = {"classteacher": HiddenInput}

在formset中,还可以使用hiddeninput小部件,或者在构造函数中使用form=Timetableform参数。同样的想法

相关问题 更多 >