【问题标题】:How to create form field for every foreign key in django?如何为 django 中的每个外键创建表单字段?
【发布时间】:2016-01-08 22:42:34
【问题描述】:

我正在尝试构建一个表单,但我不确定应该如何正确完成。这些是我的模型:

class Country(models.Model):
    name = models.CharField(max_length=250, null=False, blank=False, unique=True)
    twocode = models.CharField(max_length=5, null=False, blank=False, unique=True)

class GeoBonus(models.Model):
    name = models.CharField(max_length=250)
    country = models.ForeignKey(Country, related_name='geo_bonuses')
    bookmaker = models.ForeignKey(Bookmaker, related_name='geo_bonuses')

博彩公司有奖金,每个国家都不同。例如:

Bookmaker has bonuses:
    Slovakia: "eligible for 100% up to $200"
    Afghanistan: "eligible for 100% up to €100!"
    USA: "restricted country"
    ...

我想在 GeoBonus 中将引号中的文本保存为 name。当然我可以写使用简单的模型表格,但我会提交表格 248 次(每个国家)。我想展示每个国家的所有领域。

  • 如果name 为空白,则不会创建 GeoBonus。
  • 如果name 不为空,则创建 GeoBonus 对象。 这应该是这样的: forms.pyviews.py 中的代码是什么样的?我还需要编辑字段。

我尝试为国家/地区手动创建新字段:

<form method="post" action="" class="wide">
        {% csrf_token %}
        {%bootstrap_form form %}
        <div class="form-group">
        {%for country in countries%}
        <label class="control-label" for="{{country.twocode}}">{{country}}</label>
            <input class="form-control" id="{{country.twocode}}" maxlength="250" type="text" />
        {%endfor%}
        </div>
        <input type="submit"  class="btn btn-default" name="submit" value="Save">
    </form>

使用这个 forms.py 类:

class GeoBonusForm(forms.ModelForm):
    class Meta:
        model = GeoBonus
        fields = ['bookmaker']

request.POST 确实只包含博彩公司字段。

EDIT1:Views.py

@staff_member_required
def geo_bonus_edit(request, bookmaker=None):
    template = loader.get_template('geobonus/edit.html')
    if request.method == 'POST':
        form = GeoBonusForm(request.POST)
        print request.POST
    else:
        form = GeoBonusForm()
    context = RequestContext(request, {
        'form': GeoBonusForm,
        'countries': Country.objects.all(),
    })
    return HttpResponse(template.render(context))

【问题讨论】:

  • 能否添加视图交付模板的代码?
  • @RodrigoDela 我目前没有太多视图代码,不知道应该如何完成。但是添加了视图。

标签: django django-forms


【解决方案1】:

我建议您动态生成表单中的字段。它可能看起来像这样:

class GeoBonusForm(forms.ModelForm):
    countries = Country.objects.all()

    def __init__(self, *args, **kwargs):
        super(GeoBonusForm, self).__init__(*args, **kwargs)
        for country in self.countries:
            self.fields[country.name] = forms.CharField()

这允许您为您拥有的每个国家/地区生成一个 CharField。 因此,保存与普通 ModelForm 预期的有点不同,我建议覆盖 save 方法:

def save(self, commit=True):
    super(GeoBonusForm, self).save(commit=False)
    bookmaker = Bookmaker.objects.get(id=self.cleaned_data['bookmaker'].id)
    for field in self.cleaned_data:
        if field != 'bookmaker':
            country = Country.objects.get(name=field)
            geo_bonus, created = GeoBonus.objects.get_or_create(bookmaker=bookmaker, country=country)
            geo_bonus.name = self.cleaned_data[field]
            geo_bonus.save()

首先,我们尝试获取所选的博彩公司。之后,我们遍历清理的字段(有关表单清理的更多信息,请查看here)并尝试get_or_create GeoBonus 对象。现在我们只需填写对应country字段的值并保存即可。

我稍微修改了你的视图代码:

def index(request, bookmaker=None):
    template = loader.get_template('geobonus/edit.html')
    if request.method == 'POST':
        form = GeoBonusForm(request.POST)
        if form.is_valid():
            form.save()
    else:
        form = GeoBonusForm()
    context = RequestContext(request, {
        'form': GeoBonusForm,
    })
    return HttpResponse(template.render(context))

您不再需要将国家/地区传递给上下文,因为我们会在表单中生成字段。在POST 上,我们检查表单是否有效,如果有效则保存。

对于模板,您现在应该只需要这个:

<form action="." method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit">
</form>

希望我做对了,这可以解决您的问题。

编辑:请注意,这是一个简单的快速示例。当然,您应该清理数据并检查输入是否有效,并为更简单的保存过程做好准备。

【讨论】:

    【解决方案2】:

    您可以使用 Django 的 inlinemodelformset 来实现,请参阅 using a formset in views and templates 示例代码。

    【讨论】:

    • hmm,formset afaik 用于打印多个模型表单。但我需要为 250 个外键(国家)打印一份模型表格。
    • 那你可以使用Inline model formsets,答案更新了。
    猜你喜欢
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2023-03-26
    • 2010-10-11
    • 2022-11-13
    相关资源
    最近更新 更多