【问题标题】:Django form efficiency issueDjango表单效率问题
【发布时间】:2013-06-15 03:27:43
【问题描述】:

我继承了一些由多个开发人员处理的代码,因此,该产品没有标准。我遇到了严重的性能问题,并且正在解决很多问题,但不知道如何解决这个问题。当用户在预先填充数据并允许用户选择活动日期的页面上提交时,他们可以提交,并且任何带有日期的东西都会消失。问题出在views.py中。当用户提交时,以下代码运行,并在formset = formset(request.POST) 挂断。我假设发生了多个数据库调用,但是当我打印到终端时没有看到它们。以下是整个提交过程。

STATES = ['Routed','Reconciled']

formset = None

form = StudyOnlyForm()

study_pk = request.GET.get('study', '0')
if study_pk == '' or study_pk == '0':
    study_pk = 0

# child transactions that are 'Recoginzed',
# reportable with a 'Routed' parent
qs = Transaction.objects.filter(contract__reportable=True,
        cleared = False,
        contract__study__pk=study_pk,
        transaction_status='Recognized',
        parent_transaction__isnull=False,
        parent_transaction__transaction_status__in=STATES)

#Designed to capture standalone contracts
qs1 = Transaction.objects.filter(contract__reportable=True,
        cleared = False,
        contract__study__pk=study_pk,
        contract__contract_type__name='Standalone',
        transaction_status__in=STATES)

#Captures Arms contracts for Milestone payments
parent_list = []
arms_list = []

parent = Transaction.objects.filter(parent_transaction__isnull=True,
    contract__reportable=True,
    cleared = False,
    contract__study__pk=study_pk,
    contract__contract_type__name='ARMs',
    transaction_status__in=STATES)

children = Transaction.objects.filter(contract__reportable=True,
        cleared = False,
        contract__study__pk=study_pk,
        transaction_status='Recognized',
        contract__contract_type__name='ARMs',
        parent_transaction__isnull=False,
        parent_transaction__transaction_status__in=STATES)

for child_item in children:
    parent_list.append(child_item.parent_transaction.pk)
    arms_list.append(child_item.pk)

for parent_item in parent:
    if parent_item.pk not in parent_list:
        arms_list.append(parent_item.pk)

qs3 = Transaction.objects.filter(pk__in=arms_list)

qs4 = qs | qs1 | qs3

qs = qs4.order_by('-pk')

formset = modelformset_factory(Transaction, form=PaidDateForm, extra=0, can_delete=False)

if request.method == "POST":
    print 'if request.POST'
    print datetime.datetime.now()
    formset = formset(request.POST)
    print 'created formset'
    print datetime.datetime.now()
    if formset.is_valid():
        print 'formset valid'
        print datetime.datetime.now()
        updated_transactions = formset.save(commit=False)
        print 'updated transactions'
        print datetime.datetime.now()
        for trans in updated_transactions:
            if trans.paid_amount is not None and trans.date_cleared is not None:
                trans_to_change = Transaction.objects.get(pk=trans.pk)
                trans_to_change.paid_amount = trans.paid_amount
                trans_to_change.date_cleared = trans.date_cleared
                trans_to_change.paid_currency = trans_to_change.entered_currency
                trans_to_change.paid_amount_usd = 
                Decimal(str(trans_to_change.paid_amount * Decimal(str(trans_to_change.exchange_rate)).quantize(Decimal('0.01')))).quantize(Decimal('0.01'))
                trans_to_change.edited_by = request.user
                trans_to_change.cleared = True
                trans_to_change.save()
        if updated_transactions:
            messages.add_message(request, messages.INFO, 'The transactions have been updated successfully.')
            return HttpResponseRedirect(reverse('track:update_pdate'))
        else:
            messages.add_message(request, messages.INFO, 'No transactions have been updated.')

            return render_to_response(
                'track/paid_date_update.html',
                {'formset':formset,
                 'form': form,
                 'study_pk':study_pk,
                },
                context_instance=template.RequestContext(request))

else:
    formset = formset(queryset=qs)

return render_to_response(
        'track/paid_date_update.html',
        {'formset':formset,
         'form': form,
         'study_pk':study_pk,
        },
        context_instance=template.RequestContext(request))


Forms:

class StudyOnlyForm(forms.Form):
    action = forms.CharField(widget=forms.HiddenInput())
    #
    # JBL - Q4.0 changed this form to pull all studies (previously
    #       only 'active' studies), which really means all studies
    #       that are not 'ccc' studies
    #
    study = forms.ModelChoiceField(required=False,
            label='Protocol',
            queryset=Study.objects.all().exclude(study_status='ccc'))

    def __init__(self, *args, **kwargs):
        self.req = True
        if 'req' in kwargs:
            self.req = kwargs.pop('req')
        super(StudyOnlyForm, self).__init__(*args, **kwargs)
        print 'StudyOnlyForm() init'
        self.fields['study'].required = self.req

class PaidDateForm(forms.ModelForm):
    formfield_callback = jquery_datefield
    paid_amount = forms.DecimalField(label="Cleared
    Amount",max_digits=14,decimal_places=2,required=False)
    date_cleared = forms.DateField(label="Cleared Date",widget=JQueryDateWidget(),
    input_formats=settings.DATE_INPUT_FORMATS, required=False)

    class Meta:
        model = Transaction
        include = ('date_time_created')

    def __init__(self, *args, **kwargs):
        super(PaidDateForm, self).__init__(*args, **kwargs)
        print 'PaidDateForm init'
        for field in self.fields:
            if field != 'date_cleared':
                self.fields[field].widget = forms.HiddenInput()
        self.fields['paid_amount'].widget.attrs['size'] = 12
        self.initial['paid_amount'] = '%.2f' % (self.instance.usd_amount)

【问题讨论】:

  • 告诉我们formset 的来源。但我认为问题出在for trans in updated_transactions 循环中。也许有很多查询
  • 如果可能,Transaction 定义

标签: django post formset


【解决方案1】:

您在 GET 分支中限制查询集,而不是 POST 分支。这意味着 POST 分支会创建一个包含每个事务的表单集。

【讨论】:

  • 您是指页面上的每笔交易?在这种情况下,这不是一个大问题。每页不超过 10 笔交易。我知道我一定是做了太多的数据库连接,但不知道怎么做。
  • 不,我的意思是数据库中的每个事务。
  • 如果您可以提出建议,我想知道如何将帖子限制为仅 'qs' 中的项目。
  • 与您在代码的GET 分支中所做的相同:使用queryset=qs 初始化表单集。有关示例,请参阅 using a custom queryset 上的文档。
  • 将 'formset = formset(request.POST)' 更改为 'formset = formset(request.POST, Transaction.objects.filter(pk__in=qs))' 它仍然在抓取
【解决方案2】:

替换你的 for 循环:

for trans in updated_transactions.exclude(paid_amount=None, date_cleared=None).all():
    trans_to_change = Transaction.objects.get(pk=trans.pk)
    trans_to_change.paid_amount = trans.paid_amount
    trans_to_change.date_cleared = trans.date_cleared
    trans_to_change.paid_currency = trans_to_change.entered_currency
    trans_to_change.paid_amount_usd = Decimal(str(trans_to_change.paid_amount * Decimal(str(trans_to_change.exchange_rate)).quantize(Decimal('0.01')))).quantize(Decimal('0.01'))
    trans_to_change.edited_by = request.user
    trans_to_change.cleared = True
    trans_to_change.save()

【讨论】:

  • 这是个好主意,但我仍然不知道为什么我在 'formset = formset(request.POST)' 处有 90 秒的时间跨度
  • 那么,将 request.POST 解析到表单集需要很长时间......表单/表单集和模型是什么样的?要查看 SQL 查询,您可以将 django-debug-toolbar 应用程序添加到您的应用程序中。非常方便。
  • 我添加了表单和视图的其余部分
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 2011-10-30
  • 1970-01-01
相关资源
最近更新 更多