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

Posted

技术标签:

【中文标题】将视图中的选择传递给表单【英文标题】:Pass choices from views to form 【发布时间】:2016-05-11 22:08:15 【问题描述】:

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

我正在尝试,但它给了我 ValueError: too many values to unpack (expected 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

但它说选择是不确定的

【问题讨论】:

【参考方案1】:

完成!

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

谢谢

【讨论】:

酷,你成功了。是的,init 方法是一个很好的补充。您需要在渲染之前对信息进行更多处理。看起来不错【参考方案2】:

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

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

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

【讨论】:

它给出一个错误:AttributeError: 'tuple' object has no attribute 'get'。模板渲染期间出错。错误在 hidden 行。也许可以帮助知道我的选择 = options.new_affiliation.all() 打印的是: [, ], 你的选择 = tuple(options.new_affiliation.all().values())打印的是:('id': 1, 'name': 'Red', 'id': 2, 'name': 'Black')。这里最后一行报错dpaste.com/30AY564 @fabio 您可能希望以不同的格式发送它,以便它在没有任何关键字的情况下可读。你可以这样做:choices = tuple(options.new_affiliation.all().get('name').values()) 这将只检索像 (('Black'), ('Red')) 这样的名称-- 基于这里的sn-ps,确定到底发生了什么仍然有点困难,所以试着多弄点结果,然后回复更多信息。我可以在自己的 IDE 中尝试其中的一些代码,看看它是否会产生理想的结果。 我不知道给你什么信息...我编辑了我的第一篇文章添加了一些东西。也许问题在于它接受像字段这样的选择并尝试在模板上呈现它......也许我们应该在一些 init 方法中传递选择? 这是它应该如何工作的: 1) 在开始时数据库不存在。 2) 我使用第一次迁移创建数据库 3) 我用脚本填充数据库。我创建了一些附属对象。 4) 我创建了一个且只有一个选项对象。在 new_affilation 字段中,我只选择了一些从属对象 5) 用户可以创建一个横幅,在我在 pass4 中为他们选择的那些之间只选择一个从属关系 6) 有时我会修改选项对象以允许在新横幅中使用不同的从属关系。我希望这能澄清

以上是关于将视图中的选择传递给表单的主要内容,如果未能解决你的问题,请参考以下文章

从视图中,如何将自定义“选择”传递到表单的 ChoiceField?

将选择表单传递给数据库以填充数据表

选择时将值从 TabBarController 传递给子视图控制器

python Django:将表单视图中的变量传递给表单

如何将复杂的键值参数表单视图传递给mvc中的控制器?

选择 Swift 时将注释标题传递给嵌入式容器视图