如何仅将初始值设置为 Django 内联表单集中的额外字段

Mah*_*fuz 7 python django django-forms inline-formset

我对DjangoPython还很陌生,所以请耐心等待。我正在尝试创建一个如下所示的表格时间表。

时间表表格:

在此处输入图片说明

预期结果

我想要实现的是,当我调用特定的时间表时,我应该获取所有相关的时间表详细信息数据并以与工作日期/项目组合相关的所有小时数都在同一行中的方式填充上面的表格,并且相关小时数是放置在相应的工作代码下(即在图片中,第 1 行在“规范”下有 8 小时,第 2 行在 RnR 下有 12 小时)

问题

现在如何设置初始值以根据工作日/项目组合的工作代码在每一行中填充正确的小时单元格(与模型字段无关)?

其次,如果同一工作日/项目的时间是分开的(例如标准 4 小时和 Annu 4 小时),我该如何处理?我如何把它放在同一行?如果我可以使用字典来填充这会很容易吗?

由于我在 10/80/20... 字段的表单中没有任何初始数据,因此我无法检查是否删除了任何小时数,以便我也可以删除该记录。

我开始质疑自己,我的内联森林方法在这种情况下是否有效?

所以底线是我如何在这个表单中填充这些不相关的表单字段?

我愿意接受任何方法或想法来实现这一目标,并感谢您的帮助。

如果您发现我做错了什么,请随时纠正我,以便我学习。

代码

模型.py

class Workcode(models.Model):
    workcode = models.PositiveSmallIntegerField()
    workcode_description = models.CharField(max_length=20)
    workcode_short = models.CharField(max_length=4)
    workcode_serial = models.SmallIntegerField()

class Project(models.Model):
    project = models.CharField(max_length=10)

class Employee(models.Model):
    name = models.CharField(max_length=10)

class WeekendDate(models.Model):
    weekenddate = models.DateField(unique=True)

class Timesheet(models.Model):
    employee = models.ForeignKey(Employee)
    weekenddate = models.ForeignKey(WeekendDate)

    class Meta:
        unique_together = ('employee', 'weekenddate')

class TimesheetDetail(models.Model):
    timesheet = models.ForeignKey(Timesheet)
    workcode = models.ForeignKey(Workcode)
    project = models.ForeignKey(Project)
    workdate = models.DateField()
    hours = models.PositiveSmallIntegerField()

    class Meta:
        unique_together = ('timesheet','workcode','project','workdate')
Run Code Online (Sandbox Code Playgroud)

表格.py

class TimesheetForm(forms.ModelForm):
    class Meta:
        model = models.Timesheet
        fields = "__all__"

class BaseTimesheetInlineFormSet(BaseInlineFormSet):

    def add_fields(self, form, index):
        super(BaseTimesheetInlineFormSet, self).add_fields(form, index)
        form.fields['10']   = forms.IntegerField(max_value=16, min_value=0, label='Norm', required=False)
        form.fields['80']   = forms.IntegerField(max_value=16, min_value=0, label='RnR', required=False)
        form.fields['20']   = forms.IntegerField(max_value=16, min_value=0, label='Annu', required=False)
        form.fields['21']   = forms.IntegerField(max_value=16, min_value=0, label='Sick', required=False)
        form.fields['25']   = forms.IntegerField(max_value=16, min_value=0, label="Carer", required=False)
        form.fields['26']   = forms.IntegerField(max_value=16, min_value=0, label='LSL', required=False)
        form.fields['13']   = forms.IntegerField(max_value=16, min_value=0, label='Night', required=False)
        form.fields['14']   = forms.IntegerField(max_value=16, min_value=0, label="Noon", required=False)
        form.fields['71']   = forms.IntegerField(max_value=16, min_value=0, label='Bus', required=False)
        form.fields['22']   = forms.IntegerField(max_value=16, min_value=0, label='WComp', required=False)



TimesheetDetailInlineFormset = inlineformset_factory(models.Timesheet,
                                                models.TimesheetDetail,
                                                form = TimesheetForm,
                                                formset=BaseTimesheetInlineFormSet,
                                                # fields=('workdate','project'),
                                                fields='__all__',
                                                extra=7, max_num=9)
Run Code Online (Sandbox Code Playgroud)

视图.py

def manage_timesheet1(request, timesheet_id):
"""Edit children and their addresses for a single parent."""

initial_data = [{'workcode': 1, 'project':1, 'workdate': '2017-12-29', 'hours':10, },
                {'workcode': 1, 'project':1, 'workdate': '2017-12-30', 'hours':8, }]

timesheet = Timesheet.objects.get(pk=timesheet_id)
if request.method == 'POST':
    formset = TimesheetDetailInlineFormset(request.POST, request.FILES, instance=timesheet)

    if formset.is_valid():

        # This development will be in a saperate branch called 'alternet-time-save'#
        converted_data = []
        wc_list = ['10','80','20,','21','25','26','13','14','71','22']
        # with transaction.atomic():
        for form in formset:
            if form.has_changed():
                obj = form.save(commit=False)
                obj.timesheet = timesheet
                obj.workcode = Workcode.objects.get(id=5)
                for k,v in form.cleaned_data.items():
                    if k in wc_list and k in form.changed_data:
                        if v is not None:
                            obj, created = TimesheetDetail.objects.update_or_create(
                                    # pk = form.cleaned_data['id'].id,
                                    timesheet = timesheet,
                                    workcode = Workcode.objects.get(workcode=k),
                                    project = form.cleaned_data['project'],
                                    workdate = form.cleaned_data['workdate'],
                                    defaults = {
                                        'timesheet' : timesheet,
                                        'workcode' : Workcode.objects.get(workcode=k),
                                        'project' : form.cleaned_data['project'],
                                        'workdate' : form.cleaned_data['workdate'],
                                        'hours' : v
                                        })

        return redirect('timesheet:timesheetlist')
    else:
        print(formset.errors)
else:
    # formset = TimesheetDetailInlineFormset(instance=timesheet, initial=initial_data)
    formset = TimesheetDetailInlineFormset(instance=timesheet)


if request.is_ajax():
    return render(request, 'timesheet/_ajax_manage_timesheet.html', {
                  'children_formset':formset, 'timesheetid':timesheet_id})
else:
    return render(request, 'timesheet/manage_timesheet.html', {
                  'children_formset':formset, 'timesheetid':timesheet_id})
Run Code Online (Sandbox Code Playgroud)