将视图中的选择传递给表单

时间:2016-02-02 22:09:14

标签: python django forms views choicefield

我使用Bannerform形式通过Banner视图(和模板)创建新的add_banner对象。我使用课程Options来确定affiliationBannerform字段中允许的affiliation个对象。

我正在尝试将视图中的选项传递给表单但是它给了我ValueError:解压缩的值太多了(预期2)

我的代码在new_affiliation是ForeignKey时起作用,但现在我需要更多的值。我认为我必须明确views中的“选择”,否则我将在第一次迁移时遇到问题(它似乎从models.py调用数据库表而不是views.py调用数据库表,所以如果我将Options.objects.get(id=1)放在models.py上它会给出错误,因为表格还不存在。“

我的form.py

from django import forms
from core.models import Options, Banner, Affiliation #somethings other

class BannerForm(forms.ModelForm):
    name = forms.CharField(max_length=32)
    affiliation = forms.ChoiceField('choices')
    #affiliation = forms.ModelChoiceField('choices') #same error
    class Meta:
        model = Banner
        exclude = (#some fields)

我的models.py

from django.db import models
from django.contrib.auth.models import User
from django import forms

class Options(models.Model):
    new_affiliation = models.ManyToManyField('Affiliation')
    #new_affiliation = models.ForeignKey('Affiliation') #this worked (with some changes in views)

class Affiliation(models.Model):
    name = models.CharField(max_length=32, unique=True)

class Banner(models.Model):
    name = models.CharField(max_length=32, unique=True)
    affiliation = models.ForeignKey(Affiliation)

我的views.py

def add_banner(request):
    if request.method == 'POST':
        #some code here
    else:
        options = Options.objects.get(id=1)
        print(options.new_affiliation.all()) #controll
        choices = options.new_affiliation.all()
        print(choices) #controll
        form = BannerForm(choices, initial={            
            #some code regarding other fields
            })       
    return render(request, 'core/add_banner.html', {'form': form})

我的add_banner.html

<form role="form" id="banner_form" enctype="multipart/form-data "method="post" action="../add_banner/">

  {% csrf_token %}
  {% for hidden in form.hidden_fields %}
  {{ hidden }}
  {% endfor %}

  {% for field in form.visible_fields %}
    {{ field.errors }}
    {{ field.label }}
    {{ field }}      
    {{ field.help_text }}
    <br />
  {% endfor %}

任何帮助都会被贬低。

更新。我只更改了views.py

def add_banner(request):
    if request.method == 'POST':
        #some code here
    else:
        options = Options.objects.get(id=1)
        print(options.new_affiliation.all()) #controll
        choices = tuple(options.new_affiliation.all())
        print(choices) #controll
        form = BannerForm(choices, initial={            
            #some code regarding other fields
            })       
    return render(request, 'core/add_banner.html', {'form': form})

但仍然给出错误。

更新2.如果我直接从form.py传递选项,它可以工作: 我的views.py

def add_banner(request):
    if request.method == 'POST':
        #some code here
    else:
        form = BannerForm(request.POST or None, initial={
            #some code regarding other fields
            })
    return render(request, 'core/add_banner.html', {'form': form})

我的forms.py

class BannerForm(forms.ModelForm):
    options = Options.objects.get(id=1)
    choices = options.new_affiliation.all()
    name = forms.CharField(max_length=32)
    affiliation = forms.ModelChoiceField(choices)

不幸的是,这会给第一次迁移带来问题(见上文)。

我正在尝试使用一些init方法传递选择......

我的forms.py

class BannerForm(forms.ModelForm):
    name = forms.CharField(max_length=32)
    affiliation = forms.ModelChoiceField(choices)

    def __init__(self, *args, **kwargs):
        options = Options.objects.get(id=1)
        choices = options.new_affiliation.all()
        #choices = kwargs.pop('choices')
        super(RegentForm, self).__init__(*args, **kwargs)
        self.fields['affiliation'] = choices

但它说选择不明确

2 个答案:

答案 0 :(得分:2)

从我在这里看到的,看起来你得到一个错误&#34;解包的数量太多&#34;因为你没有发送&#34;选择&#34;作为正确的类型。 ChoiceField仅将选项视为元组,如the documentation中所示的模型。如果您希望基于QuerySet定义选项,则必须将其转换为可以解释为有效&#34;选择&#34;的元组。例如,在我的一个项目中,我需要准备一组年份作为元组,以便我可以允许用户从预定年份列表中进行选择。我指定了以下函数来执行此操作:

def years():
    response = []
    now = datetime.utcnow()
    for i in range(1900, now.year + 1):
        response.append([i, str(i)])
    return tuple(response)

由于元组是不可变的,因此仅仅基于原则来构建它们通常不是一个好主意。但是,在这种情况下,似乎有必要作为一种措施来声明您对这些陈述可能存在的可变性是正确的。

在您的具体情况下,您可能会考虑这样做:

choices = tuple(options.new_affiliation.all().values())

我还没有测试过这段代码,坦率地说,我对你的项目并不完全熟悉,可能会在这个回复的某些部分出错。因此,可能需要进一步调整,但试一试。根据您的错误,这绝对是程序目前正在破坏的地方。如果您取得任何进展,请在此处更新。

答案 1 :(得分:2)

完成!

我的form.py

class BannerForm(forms.ModelForm):
    name = forms.CharField(max_length=32, label='Nome')

    def __init__(self, *args, **kwargs):
        options = Options.objects.get(id=1)
        choices = options.new_affiliation.all()
        super(BannerForm, self).__init__(*args, **kwargs)
        self.fields['affiliation'] = forms.ModelChoiceField(choices)
        self.fields['affiliation'].initial = choices

    class Meta:
        model = Banner

我的views.py

def add_banner(request):
    if request.method == 'POST':
        #some code here
    else:
        form = BannerForm(request.POST or None, initial={
        #some code here
            })
    return render(request, 'core/add_banner.html', {'form': form})

谢谢