将选项从视图传递到表单

Pass choices from views to form

我使用 Bannerform 形式通过 add_banner 视图(和模板)创建新的 Banner 对象。我使用 class Options 来确定在 Bannerformaffiliation 字段)形式中允许哪些 affiliation 对象。

我正在尝试将选项从视图传递到表单,但它给了我 ValueError:要解压的值太多(预期为 2)

我的代码在 new_affiliation 是 ForeignKey 时有效,但现在我需要更多值。我想我必须在 views 中确定 'choices' 否则我会在第一次迁移时遇到问题(它似乎是从 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)

不幸的是,这会在第一次迁移时出现问题(见上文)。

我正在尝试使用一些初始化方法来传递选择...

我的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

但它说选择是不确定的

从我在这里看到的情况来看,您似乎收到了一个错误 "too many values to unpack",因为您没有将 "choices" 作为正确的类型发送。 ChoiceField 仅将选择作为元组,如模型的 the documentation 所示。如果您希望基于 QuerySet 定义选择,则必须将其转换为可以解释为有效 "choices" 的元组。例如,在我的一个项目中,我需要准备一组年份作为元组,以便我可以允许用户从预先确定的年份列表中 select。我指定了以下函数来执行此操作:

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())

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

完成!

我的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})

谢谢