将ForeignKey对象转换为ChoicesField

时间:2016-07-14 16:37:04

标签: python django django-models django-views

我有一个名为Space的模型,它有一个名为guest的字段,该字段是一个带有单个数字的选择字段,比方说3并将其保存在数据库中。我有另一个名为Book的模型,其字段为no_of_persons

现在,我是否可以过滤'guest'字段值'3'Book模型,并将其显示为下拉列表(1,2,3)超过guest模型中保存的数字。?

回想一下,guest保存为单个数字。是否可以从最低数字开始显示下拉列表?

我正在尝试做的一个很好的例子是Airbnb上'Guests'字段的值与'Booking'模型中'Guests'字段的对应关系。

enter image description here

更新

在尝试Todor的建议后得到以下错误。

coercing to Unicode: need string or buffer, int found

模型

class Space(models.Model):
    user= models.ForeignKey(User)
    no_of_guest=models.CharField(max_length=30, choices=MAX_SPACE_CHOICES, verbose_name='no_of_guest')
    #other fields

    def __unicode__(self):
        return '%s, %s, %s, %s, %s' % (self.user, self.id, self.name, self.address, self.no_of_guest)

class BookSpace(models.Model):
    user= models.ForeignKey(User)
    space= models.ForeignKey(Space)
    check_in_date= models.DateField()
    check_out_date= models.DateField()
    no_of_persons= models.CharField(max_length=10)
    #other fields

    def __unicode__(self):
        return '%s, %s, %s' % (self.user, self.space, self.full_name)

class BookSpaceForm(forms.ModelForm):
    class Meta:
        model= BookSpace
        exclude=('#fields not needed')

    def __init__(self, *args, **kwargs):
        space= kwargs.pop('space')
        super(BookSpaceForm, self).__init__(*args, **kwargs)
        guest_choices= [(i, str(i)) for i in range(1,  int(space.no_of_guest)+1)]
        self.fields['no_of_persons'].widget=  forms.ChoiceField(choices=guest_choices)

更新后,我正在

KeyError异常 u'space” 例外位置: init 中的models.py,第202行

该行是:

space= kwargs.pop('space')

在我看来:

def book_a_space(request, space_id):
    space= Space.objects.get(pk=space_id)
    if request.method=="POST":
        form=BookSpaceForm(request.POST)
        if form.is_valid():
            #other data and more
        else:
            print form.errors

    else:
        form=BookSpaceForm(space=space)
        return render(request, 'spaceb/book_space_form.html', {'BookSpaceForm':BookSpaceForm})

在模板中:

{{  BookSpaceForm.as_p }}

更新:

仍然得到KeyError。我修改了这样的模型:

def __init__(self, *args, **kwargs):
    space_id= kwargs.pop('space_id')
    super(BookSpaceForm, self).__init__(*args, **kwargs)
    if space_id:
        guest_choices = [(str(i), str(i)) for i in range(1, int(space_id.no_of_guest)+1)]
        self.fields['no_of_persons'].widget = forms.ChoiceField(choices=guest_choices)

在我看来,我做了

def book_a_space(request, space_id):
        space= Space.objects.get(pk=space_id)
        if request.method=="POST":
            form=BookSpaceForm(request.POST)
            if form.is_valid():
                #other data and more
            else:
               print form.errors

        else:
            context = {
               'BookSpaceForm': BookSpaceForm(space_id=space_id),
                'space_id': Space.objects.get(id=space_id)
            }
           return render(request, 'spaceb/book_space_form.html', context)

我收到了这个错误:

 'unicode' object has no attribute 'no_of_guest'

我更改了BookSpace模型中的 unicode 以返回:

return '%s, %s, %s' % (self.user, self.space_id.no_of_guest, self.full_name)

然而..仍然得到相同的unicode错误。

1 个答案:

答案 0 :(得分:1)

您可以创建一个自定义Book表单,该表单在构建时接受guest实例,并使用选择框动态更改no_of_persons字段的窗口小部件。

示例实现:

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        space = kwargs.pop('space')
        super(BookForm, self).__init__(*args, **kwargs)
        guest_choices = [(str(i), str(i)) for i in range(1, int(space.no_of_guest)+1)]
        self.fields['no_of_persons'].widget = forms.Select(choices=guest_choices)


#sample usage
def book_a_space(request, space_id):
    space = Space.objects.get(pk=space_id)
    if request.method == "POST":
        form = BookSpaceForm(request.POST, space=space)
        if form.is_valid():
            #other data and more
        else:
           print form.errors
    else:
        form = BookSpaceForm(space=space)

    return render(request, 'spaceb/book_space_form.html', {
        'form': form,
        'space': space,
    })