Django表单__init__方法似乎被调用两次

时间:2017-02-01 16:15:12

标签: python django validation form-submit python-multithreading

在我的一个Django网页上,我为数据库中的特定模型(Meeting)的每个实例显示一个图标(每个模型实例一个图标)。

当用户单击其中一个图标时,表单将显示在页面的其他位置,以允许用户输入有关该特定模型实例的详细信息。一旦他们输入了表单上字段字段的所有详细信息,他们就可以按“上传”按钮将输入的信息上传到数据库(并将信息保存到该模型的实例中)。

提交表单后,页面将刷新,显示特定模型的每个实例的图标。如果用户单击现有图标,并对其表单上的任何字段进行更改,并单击“上载”,则会创建该模型的新实例,并使用填充了这些修改字段的表单。

每次单击“上传”按钮都应在数据库中再创建一个Meeting模型实例。表单上的每个字段代表Meeting模型的属性之一。

我在表单上有两个按钮,用于将图像文件附加到Meeting的实例,其中一个当前有效 - 当我用它来附加图像时,点击“上传”,页面是刷新,图像显示附加到该模型实例的表单。

但是,当我在使用其他按钮附加图片后单击“上传”时,页面会刷新,并且网页上会显示Meeting模型的其他几个实例,其中包含所有字段表格留空,并且没有附加图像文件(尽管还创建了一个图像文件,保存为已输入的所有字段,并且附加了图像文件)。

在尝试找出为什么在通过此特定按钮上传图像时创建了Meeting个对象的多个实例时,我在代码中添加了一些调试,特别是对于我的形式用于上传此信息&这些图像到数据库:

class BudgetPresentationForm(ValidatedForm):
    """ Provides the form for the formset BudgetPresentationFormset """
    presentation_minutes = EasyText(field_class="medium", label='Client presentation notes')
    presentation_date = MoonDateTimeField(required=False, widget=forms.DateTimeInput(format='%d/%m/%Y %H:%M', attrs=({'class':'datetimepicker presentation_date', 'name':'presentation_date2'})))
    presenter1 = forms.CharField()
    presenter2 = forms.CharField()
    presenter3 = forms.CharField()
    presenter4 = forms.CharField()

    class Meta:
        model = Budget
        fields = ('presentation_minutes', 'presenter1', 'presenter2', 'presenter3', 'presenter4', 'presentation_date', 'pdf_package_dep')

    def __init__(self, *args, **kwargs):
        self.instance = kwargs.get('instance', {})
        budget = self.instance

        if hasattr(budget, 'id'):
            self.presenters = budget.presenters.all()

            if budget.presentation_date:
                print("Budget meeting: ", budget.meeting)
                pres_meeting = budget.meeting or Meeting.objects.create(project=budget.project, purpose='7')
                print("Meeting created in projects/forms.py BudgetPresentationForm (line 1055): ", pres_meeting)
                self.pres_meeting_id = pres_meeting.id
                self.pres_meeting_creator = pres_meeting.event_creator or ''
                if not budget.meeting:
                    budget.meeting = pres_meeting
                    budget.save()
                if not budget.meeting or not pres_meeting.date:
                    pres_meeting.date = budget.presentation_date
                    pres_meeting.save()
                print("Meeting object is: ", pres_meeting.id)
                #print("Process ID: ", os.getpid())
        else: self.presenters = []

        super(BudgetPresentationForm, self).__init__(*args, **kwargs)
        # if hasattr(self, 'pres_meeting_id'): self.fields['presentation_date'].widget.attrs['data-meeting-id'] = self.pres_meeting_id
        self.fields['presentation_date'].widget.attrs.update({'data-meeting-id': getattr(self,'pres_meeting_id', ''), 'data-meeting-creator': getattr(self,'pres_meeting_creator', '')})

        initial_presenters = [(e.id, e.full_name) for e in self.presenters]+[None, None, None, None]#[(None, ''), (None, ''), (None, ''), (None, '')] # Always at least four so that first four can populate form fields
        if initial_presenters[0]: self.fields['presenter1'] = FlexiSelect(initial=[initial_presenters[0]], current_id='', url_code='ee', choices=[], required=False, instant='', class_name="autocomplete", label='Who is presenting')
        else: self.fields['presenter1'] = FlexiSelect(initial=[(None, '')], current_id='*', url_code='ee', choices=[], required=False, instant=' instant', class_name="autocomplete", label='Who is presenting')
        if initial_presenters[1]: self.fields['presenter2'] = FlexiSelect(initial=[initial_presenters[1]], current_id='', url_code='ee', choices=[], required=False, instant='', class_name="autocomplete", label='')
        else: self.fields['presenter2'] = FlexiSelect(initial=[(None, '')], current_id='*', url_code='ee', choices=[], required=False, instant=' instant', class_name="autocomplete", label='')
        if initial_presenters[2]: self.fields['presenter3'] = FlexiSelect(initial=[initial_presenters[2]], current_id='', url_code='ee', choices=[], required=False, instant='', class_name="autocomplete", label='')
        else: self.fields['presenter3'] = FlexiSelect(initial=[(None, '')], current_id='*', url_code='ee', choices=[], required=False, instant=' instant', class_name="autocomplete", label='')
        if initial_presenters[3]: self.fields['presenter4'] = FlexiSelect(initial=[initial_presenters[3]], current_id='', url_code='ee', choices=[], required=False, instant='', class_name="autocomplete", label='')
        else: self.fields['presenter4'] = FlexiSelect(initial=[(None, '')], current_id='*', url_code='ee', choices=[], required=False, instant=' instant', class_name="autocomplete", label='')

BudgetPresentationFormset = inlineformset_factory(Project, Budget, form=BudgetPresentationForm, max_num=30, extra=1, can_delete=False)

但是,当我点击此表单的“提交”按钮,将信息输入所有字段,并将图像文件附加到表单后,我的控制台显示内部代码:

if budget.presentation_date:

运行两次...即我在控制台中获得了相同的输出,其中只有一次执行此代码(即在重新加载网页时执行,在提交表单后)。

控制台输出显示:

  

('预算会议:',)

     

('在projects / forms.py BudgetPresentationForm(第1055行)中创建的会议:',)

     

('会议对象是:',11012L)

     

('预算会议:',)

     

('在projects / forms.py BudgetPresentationForm(第1055行)中创建的会议:',)

     

('会议对象是:',11078L)

让Google知道为什么会发生这种情况,似乎代码是由两个独立的线程执行的,这就是为什么它会被运行两次......

是这样的吗?为什么会这样呢?如何确保代码只运行一次,并且我的数据库中没有重复信息?

我之前没有使用过很多线程,所以我不确定如何做什么/怎么办....

修改

根据评论&回答 - 我使用formset的地方位于view的{​​{1}}(我正在显示这些演示文稿的页面,以及输入详细信息的表单) concept):

Meeting

def concept(request, project_id): project = Project.objects.prefetch_related('budget_versions').get(id=project_id) deposit = Deposit.objects.get_or_create(project=project)[0] presentations = project.budget_versions.select_related('meeting').prefetch_related('budget_items', 'cci_items', 'presenters').filter(version_number__isnull=False).annotate(vn=F('version_number') * -1).order_by('presentation_date', 'created', '-vn') end_details = EndDetails.objects.get_or_create(project=project)[0] presentation_formset = BudgetPresentationFormset(prefix="presentations", instance=project, queryset=presentations) drawing_formset = DrawingUploadFormset(prefix="drawings", queryset=Drawing.objects.filter(budget__in=presentations).order_by('budget__presentation_date', 'budget__created')) context = { 'project': project, 'presentations': presentations, 'presentation_formset': presentation_formset, 'drawing_formset': drawing_formset, 'deposit_form': DepositInfoForm(instance=deposit), 'ended_form': EndDetailsForm(instance=end_details), 'budget_notes_form': BudgetNotesForm(instance=project.budget_overview), } return render(request, 'projects/concept.html', context) upload_budget_pdfs(request, project_id):,(view用于尝试将PDF上传到表单(即我用来'附加'PDF到{形式):

view

1 个答案:

答案 0 :(得分:0)

通过formset意味着您有一个表格将重复一组项目。您必须显示代码在何处/如何使用该formset。可能这就是问题的起源所在。

Link to Django Formsets