不刷新的Django表单类

Posted

技术标签:

【中文标题】不刷新的Django表单类【英文标题】:Django forms class that does not refresh 【发布时间】:2012-10-29 15:11:59 【问题描述】:

我注意到我的一个使用 apache/mod_wsgi 运行的 Django 应用程序有一个奇怪的行为。有一个屏幕显示一个表单,基本上是一个下拉列表,其中列出了安排给定站点的可用性列表,根据给定的每周容量(3 个站点/周)与已在给定站点安排的站点总数之间的差异计算周。

此表单(ScheduleForm)是从以下视图(followup/views.py)呈现的:

def schedule(request, site_id):
    site = Site.objects.get(pk=site_id)
    if request.method == 'POST':
        form = ScheduleForm(request.POST)
        if form.is_valid():
            (year, week) = request.POST['available_slots'].split('/')
            site.scheduled = week2date(int(year), int(week[1:]))
            site.save()
            return HttpResponseRedirect('/stats/')
    else:
        form = ScheduleForm()

    return render_to_response('followup/schedule_form.html',
            'form': form,
            'site': site
        , context_instance=RequestContext(request))

这里是表单类(followup/forms.py):

class ScheduleForm(forms.Form):
    """
    Temporary lists
    """
    schedules = Site.objects.filter(
            scheduled__isnull=False
        ).values('scheduled').annotate(Count('id')).order_by('scheduled')
    integration = 
    available_integration = []

    # This aggregates all schedules by distinct weeks
    for schedule in schedules:
        if schedule['scheduled'].strftime('%Y/W%W') in integration.keys():
            integration[schedule['scheduled'].strftime('%Y/W%W')] += schedule['id__count']
        else:
            integration[schedule['scheduled'].strftime('%Y/W%W')] = schedule['id__count']

    for w in range(12): # Calculates availability for the next 3 months (3months*4 weeks)
        dt = (date.today() + timedelta(weeks=w)).strftime('%Y/W%W')
        if dt in integration.keys():
            capacity = 3-integration[dt]
        else:
            capacity = 3

        if capacity>0:
            available_integration.append([dt, capacity])

    """
    Form
    """
    available_slots = forms.ChoiceField(
        [[slot[0], '%s (%s slots available)' % (slot[0], slot[1])] for slot in available_integration]
    )

class IntegrateForm(forms.Form):
    integrated_on = forms.DateField(widget=AdminDateWidget())

这实际上可以正常工作,但唯一的问题是在安排站点时不会刷新可用性列表,除非我每次安排站点时都重新启动 apache 进程。

就好像可用性列表会被表单类缓存...

任何想法都会受到热烈欢迎。提前感谢您的任何帮助。

【问题讨论】:

Sebastien 我编辑了您的问题以包含您更正的表格。如果您有时间,请删除您的答案,因为它应该是您原始问题中的edit @Sebastien 请参阅here,了解您的答案未被删除的原因。 【参考方案1】:

这与 python 的工作方式有关,而不是 django。

下面这段代码

class ScheduleForm(forms.Form):
    """
    Temporary lists
    """
    schedules = Site.objects.filter(
            scheduled__isnull=False
        ).values('scheduled').annotate(Count('id')).order_by('scheduled')
    integration = 
    available_integration = []

将只评估一次 - 当服务器启动时。

您不应该在class 级别上做这些事情,而应该在instance 级别上做这些事情。 很可能在表单的 __init__ 方法中。

请看下面的例子:

Django - change min_length in form __init__?

django model form, restrict choices based on value in ForeignKey model

Django "dynamic" verification form (updated)

【讨论】:

完全正确...我已经修改了我的代码,现在它就像一个魅力:)【参考方案2】:

我已按如下方式修改了我的代码,现在它就像一个魅力 :) 我在这里提供它以防遇到类似问题的任何人。

class ScheduleForm(forms.Form):
    available_slots = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super(ScheduleForm, self).__init__(*args, **kwargs)

        schedules = Site.objects.filter(
                scheduled__isnull=False
            ).values('scheduled').annotate(Count('id')).order_by('scheduled')
        integration = 
        available_integration = []

        # This aggregates all schedules by distinct weeks
        for schedule in schedules:
            if schedule['scheduled'].strftime('%Y/W%W') in integration.keys():
                integration[schedule['scheduled'].strftime('%Y/W%W')] += schedule['id__count']
            else:
                integration[schedule['scheduled'].strftime('%Y/W%W')] = schedule['id__count']

        for w in range(12): # Calculates availability for the next 3 months (3months*4 weeks)
            dt = (date.today() + timedelta(weeks=w)).strftime('%Y/W%W')
            if dt in integration.keys():
                capacity = 3-integration[dt]
            else:
                capacity = 3

            if capacity>0:
                available_integration.append([dt, capacity])

        self.fields['available_slots'].choices = [[slot[0], '%s (%s slots available)' % (slot[0], slot[1])] for slot in available_integration]

【讨论】:

以上是关于不刷新的Django表单类的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Django、Ajax、jQuery 在不刷新页面的情况下提交表单?

刷新时重新提交的django表单

单击表单复选框并传递复选框布尔值时如何在Django中刷新view.py?

当浏览器中的值更改时如何刷新 django 管理表单?

使用 bootstrap 和 django 的异步表单

毕业设计——Django项目网页刷新表单重复提交问题