CheckboxSelectMultiple和ManyToManyField与Modelform的问题

时间:2011-06-18 02:28:09

标签: django django-models django-forms

我对Django很新(实际上是4个月),过去2天我一直在努力解决这个问题,我想我犯了一些愚蠢的错误。任何帮助或输入都非常感谢。我正在使用Django 1.3。

在我的模型中,

BUSINESS_GROUP = (
    ('MNC','Multinational'),
    ('INT','International (Export/Import)'),
    ('DOM','Domestic/National'),
    ('LOC','Local'),
    ('VIR','Virtual'),
)

class BusinessGroup(models.Model):
    bgroup_type = models.CharField(max_length=15, choices = BUSINESS_GROUP, blank = True, null = True)

class Business(models.Model):
    business_group_choices = models.ManyToManyField(BusinessGroup, verbose_name= "Business Group")

在表格中我有类似的东西,

def __init__(self, *args, **kwargs):
    super(BusinessForm, self).__init__(*args, **kwargs)
    self.fields['business_group_choices'].widget = forms.CheckboxSelectMultiple(choices=BUSINESS_GROUP)

在视图中,

if request.method == 'POST':
    form = BusinessForm(request.POST, instance = business)
    if form.is_valid():
        new_business = form.save(commit=False)
        new_business.created_by = request.user
        form_values = form.cleaned_data
        new_business.save()
        assign('edit_business', request.user, new_business)
        return HttpResponseRedirect(new_business.get_absolute_url())

我收到错误,

"DOM" is not a valid value for a primary key.
"INT" is not a valid value for a primary key.

我找到了source of error here in Django model source

但不清楚如何解释和解决这个问题。

修改 我尝试使字段为null = True和/或空白= True仍然得到验证错误,为什么?

随着整个设置的一些变化,我得到了这个新的错误,

Select a valid choice. [u'MNC', u'INT', u'DOM', u'LOC', u'VIR'] is not one of the available choices.

新设置: 在模型中

class BusinessGroup(models.Model):
        bgroup_type = models.CharField(max_length=15)

class Business(models.Model):
    business_group_choices = models.ManyToManyField(BusinessGroup, verbose_name= "Business Group", choices=BUSINESS_GROUP)

在表格中我有类似的东西,

def __init__(self, *args, **kwargs):
    super(BusinessForm, self).__init__(*args, **kwargs)
    self.fields['business_group_choices'].widget = forms.CheckboxSelectMultiple(choices=BUSINESS_GROUP)

2 个答案:

答案 0 :(得分:3)

我会改变一些事情......

首先,我尽量避免使用“魔法弦”。而不是:

BUSINESS_GROUP = (
    ('MNC','Multinational'),
    ('INT','International (Export/Import)'),
    ('DOM','Domestic/National'),
    ('LOC','Local'),
    ('VIR','Virtual'),
)

我愿意:

#in my_app > constants.py
MNC = 0
INT = 1
DOM = 2
LOC = 3
VIR = 4

BUSINESS_GROUP_CHOICES = (
    (MNC, 'Multinational'),
    (INT, 'International (Export/Import)'),
    (DOM, 'Domestic/National'),
    (LOC, 'Local'),
    (VIR, 'Virtual'),
)

这需要对模型进行更改,并且我已经更改了字段名称以使其更清晰:

from django.db import models

from businesses.constants import BUSINESS_GROUP_CHOICES, MNC


class BusinessGroup(models.Model):
    business_group_type = models.IntegerField(choices=BUSINESS_GROUP_CHOICES,
        default=MNC)

    def __unicode__(self):
        choices_dict = dict(BUSINESS_GROUP_CHOICES)
        return choices_dict[self.business_group_type]


class Business(models.Model):
    business_groups = models.ManyToManyField(BusinessGroup)

真正的问题在于你的形式。您需要使用ModelMultipleChoiceField,而不仅仅是重新定义窗口小部件,而不是:

from django import forms

from businesses.models import BusinessGroup


class BusinessForm(forms.ModelForm):
    class Meta:
        model = Business

    business_group = forms.ModelMultipleChoiceField(queryset=BusinessGroup.objects.all(),
                                                    widget=forms.CheckboxSelectMultiple())

这就是你得到主键错误的原因。您的BUSINESS_GROUP只是一个元组。 Django试图将你选择的元组中的值作为主键分配,显然它不能做到。相反,ModelMultipleChoiceField将执行的操作是将您选择的BusinessGroup的实例与您的业务相关联。

希望能帮到你。

答案 1 :(得分:0)

好的,我做对了, 首先,永远不要混合ManyToMany和选择,所以我的第二次尝试是完全错误的。问题出在形式上,

所以最后的解决方案看起来像,

BUSINESS_GROUP = (
    ('MNC','Multinational'),
    ('INT','International (Export/Import)'),
    ('DOM','Domestic/National'),
    ('LOC','Local'),
    ('VIR','Virtual'),
)

class BusinessGroup(models.Model):
    bgroup_type = models.CharField(max_length=15)

class Business(models.Model):
    business_group_choices = models.ManyToManyField(BusinessGroup)

而不是

class BusinessForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
    super(BusinessForm, self).__init__(*args, **kwargs)
    self.fields['business_group_choices'].widget = forms.CheckboxSelectMultiple(choices=BUSINESS_GROUP)

在表格中我有类似的东西,

class BusinessForm(forms.ModelForm):
   business_group_choices = forms.MultipleChoiceField(label="Business Group", widget=forms.CheckboxSelectMultiple, choices=BUSINESS_GROUP)

您需要将MultipleChoiceField与CheckboxSelectMultiple一起使用。

模型中的这个完全错误(混合M2M和选择),

class Business(models.Model):
    business_group_choices = models.ManyToManyField(BusinessGroup, verbose_name= "Business Group", choices=BUSINESS_GROUP)