如何在django中为每个外键创建表单字段?

时间:2016-01-08 22:42:35

标签: django django-forms

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

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对象。 它应该是这样的: GeoBonus form bootstrap forms.py views.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))

2 个答案:

答案 0 :(得分: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>

希望我做对了,这解决了你的问题。

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

答案 1 :(得分:0)

你可以使用Django的inlinemodelformset,参考using a formset in views and templates代码示例。