【问题标题】:How do I change a form value in Django?如何在 Django 中更改表单值?
【发布时间】:2013-12-01 16:46:39
【问题描述】:

我们使用 Django 1.4.3 和 django-cities-light 2.1.5 来创建我们的网站。我们正在使用表单的__init__ 方法来更新地区和城市的列表。问题是,如果用户选择了一个城市并且表单没有验证,我想将区域选择更改为所选城市的区域。代码如下:

def __init__(self, instance, *args, **kwargs):
    super(ContentItemModelForm, self).__init__(*args, instance=instance, **kwargs)
    ....
    ....
    ....
    country_id = None
    if ((hasattr(self, "initial")) and ("country_id" in self.initial)):
        country_id = int(self.initial['country_id']) if self.initial['country_id'] else None
    elif ((hasattr(self, "data")) and (u'country_id' in self.data)):
        country_id = int(self.data[u'country_id']) if self.data[u'country_id'] else None
    region_id = None
    if ((hasattr(self, "initial")) and ("region_id" in self.initial)):
        region_id = int(self.initial['region_id']) if self.initial['region_id'] else None
    elif ((hasattr(self, "data")) and (u'region_id' in self.data)):
        region_id = int(self.data[u'region_id']) if self.data[u'region_id'] else None
    city_id = None
    if ((hasattr(self, "initial")) and ("city_id" in self.initial)):
        city_id = int(self.initial['city_id']) if self.initial['city_id'] else None
    elif ((hasattr(self, "data")) and (u'city_id' in self.data)):
        city_id = int(self.data[u'city_id']) if self.data[u'city_id'] else None
    if (city_id):
        city_obj = City.objects.get(geoname_id=city_id)
        country_id = city_obj.country_id
        region_id = city_obj.region_id
        # Set current values of country_id and region_id - commented (not working).
        #self.fields['country_id'].initial = country_id
        #self.fields['region_id'].initial = region_id
    self.fields['region_id'].choices = [("", "(None)", ),]+[(obj.id, obj.name) for obj in Region.objects.filter(country_id=country_id).order_by("name")]
    if (region_id):
        self.fields['city_id'].choices = [("", "(None)", ),]+[(obj.geoname_id, obj.name) for obj in City.objects.filter(country_id=country_id, region_id=region_id).order_by("name")]
    else:
        self.fields['city_id'].choices = [("", "(None)", ),]+[(obj.geoname_id, obj.name) for obj in City.objects.filter(country_id=country_id).order_by("name")]

检查city_id、region_id和country_id当前值的代码太长,我没有找到缩短它的方法。如果没有注释,注释行(self.fields['country_id'].initial = country_idself.fields['region_id'].initial = region_id)将不起作用 - 如果仅选择国家和城市,则所选区域为“(无)”(如果表单未验证)。如果表单验证,则我们根据所选城市分配 country_id 和 region_id 值(国家和地区不保存到数据库中)。

这里是城市验证:

def clean_city_id(self):
    cleaned_data = self.cleaned_data
    country_id = cleaned_data['country_id'] if (cleaned_data.has_key('country_id')) else None
    region_id = cleaned_data['region_id'] if (cleaned_data.has_key('region_id')) else None
    city_id = cleaned_data['city_id'] if (cleaned_data.has_key('city_id')) else None
    if (not(city_id)):
        if (region_id):
            error_message = "If you select a country and a state/region, you must select a city."
            self._errors["city_id"] = self.error_class([error_message])
            raise forms.ValidationError(error_message)
        elif (country_id):
            error_message = "If you select a country, you must select a city."
            self._errors["city_id"] = self.error_class([error_message])
            raise forms.ValidationError(error_message)
    return city_id

您知道我们如何为国家和地区分配正确的值吗?

(编辑):我们希望在选择城市后的 HTML 中的正确区域中包含 selected="selected",而不是在第一个“(无)”区域中(如果用户没有选择区域) .我们使用 AJAX 在用户选择新的国家或地区后更新列表,但我们不想在加载表单后立即使用 AJAX。

谢谢, 乌里。

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    我会建议解决问题的替代方法。替代“手动”为用户设置值 - 让用户自己做。像这样:

    1) 在选择更改事件上触发表单 GET

    2) 在这些事件回调中,将表单数据传递给查看 - 就像使用 POST 一样。只做 GET 请求而不是 POST 请求。

    3) 在视图中只需将 request.GET 作为第一个参数传递给表单而不是 request.POST

    4) 让您现有的逻辑在表单 init 方法中发挥作用。

    5) 从视图中返回具有正确和有效选择的表单模板

    6) 用新表单切换现有表单。

    无论如何我都会这样做。无需分配任何东西。让用户在刷新表单后做他们可以做的选择。

    【讨论】:

    • 表单方法是post,我们不想改变它。如果用户选择新的国家或地区,我们使用 AJAX 更新城市和/或地区列表。但是当表单在用户提交后加载时,如果表单没有验证,那么我们不想使用 AJAX,我们希望表单加载正确的国家和地区(如果用户选择了一个城市)。国家始终是正确的,但如果用户在选择城市之前没有更改区域,则区域可以是“(无)”。
    • 如我所见 - 这些表格总是在选择地区和/或城市之前选择国家/地区。用户甚至不能将 city 的值更改为以前的国家/地区选择所不允许的值。但这取决于你 - 自己“神奇地”改变事物,而不是重置价值并让用户去做,用户总是觉得奇怪。在任何情况下。我提供了我能想到的最简单的解决方案。如果您不“想要”使用它,那么您将不得不“想要”更努力地工作。祝你好运。
    • 用户可以选择一个国家,将地区保留为无,然后选择一个城市。在这种情况下,他将看到所选国家/地区的所有城市。发布表单后,我们希望将区域更改为所选城市的区域,如果表单未验证也是如此。
    • 如果您只是想将区域设置为城市的区域,然后在表单保存方法或其他方式中进行,您将不必再将结果呈现给用户。那不是。如果您觉得需要向用户展示更改,请按照我的建议进行操作。以及提示用户也需要设置区域的(错误)消息。
    猜你喜欢
    • 2011-03-20
    • 2016-04-16
    • 2013-09-03
    • 2015-11-06
    • 2011-12-05
    • 1970-01-01
    • 2012-02-14
    • 2015-06-27
    相关资源
    最近更新 更多