带有select_related的Django get_object_or_404导致表单复选框widget奇怪的行为:Django 1.4 bug?

时间:2012-05-10 09:22:00

标签: django django-forms django-1.4

我带来了一个非常奇怪的Django 1.4行为,听起来像是一个bug。如果有人经历过,我会在任何地方看,但没有找到任何东西。

我关注的是使用ModelForm创建Django表单,其模型包含布尔字段。

PostTopic两个模型看起来像:

class Topic(models.Model):
    my_bool = models.BooleanField(default=False)

class Post(models.Model):
    topic = models.ForeignKey(Topic, related_name='posts')

现在,我将尝试使用TopicForm生成一个表单,在其他地方定义一个类:

post = Post.objects.get(pk=id_post)
f = TopicForm(instance=post.topic)
print f

一切正常:如果在DB my_bool中为False,则复选框。如果my_bool为True,则选中该复选框。结果如下:

<p><label for="id_my_bool">my_bool:</label> <input type="checkbox" name="my_bool" id="id_my_bool" /></p>

问题!

好的,这就是问题所在:如果我使用get_object_or_404获取Post个对象,则会始终检查my_bool字段 !看看这个:

post = get_object_or_404(Post.objects.select_related('topic'), pk=id_post)
f = TopicForm(instance=post.topic)
print f

输出(怪异):

<p><label for="id_my_bool">my_bool:</label> <input checked="checked" type="checkbox" name="my_bool" value="0" id="id_my_bool" /></p>

Nota:我尝试了其他几种获取Post对象的方法,其中一切正常

  • post = Post.objects.filter(pk=id_post)[0]
  • post = get_object_or_404(Post, pk=id_post)
  • post = Post.objects.get(pk=id_post)

唯一让它成为错误的是:

post = get_object_or_404(Post.objects.select_related('topic'), pk=id_post)

评论

你有什么想法吗?

非常感谢你!

2 个答案:

答案 0 :(得分:3)

在我的应用中遇到同样的错误并找到opened ticket。 看来主要的问题是对 select_related&amp; MySQL :MySQL返回布尔值的整数,但Django在使用select_related时无法将它们与相应的模型相关联;因此, CheckboxInput 获取值0而不是False,并将其视为复选框列表中的值。

你可以:

  1. 使用票证补丁;
  2. 或避免使用 select_related ;
  3. 或修补 CheckboxInput 小部件:

    class SingleCheckboxInput(forms.CheckboxInput):
        def render(self, name, value, attrs=None):
            if value in (0, 1):
                value = bool(value)
            return super(SingleCheckboxInput, self).render(name, value, attrs)
    
    class TopicForm(django.forms.ModelForm):
        class Meta:
            model = Topic
            widgets = {'my_bool': SingleCheckboxInput}
    

答案 1 :(得分:0)

我看到一个类似的错误,如果我取消选中所有框,POST数据为空!如果我只检测一个,则POST数据到达。而不是调用get_object_or_404(),检查您的入站request.POST数据。