【问题标题】: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

但它说选择是不确定的

【问题讨论】:

    标签: python django forms views choicefield


    【解决方案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) 有时我会修改选项对象以允许在新横幅中使用不同的从属关系。我希望这能澄清
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    相关资源
    最近更新 更多