将ModelMultipleChoiceField的查询集动态设置为自定义记录集

时间:2010-05-17 05:44:15

标签: python django django-admin

我已经看到了关于如何设置ModelMultipleChoiceField以使用自定义查询集的所有方法,我已经尝试过它们并且它们有效。但是,它们都使用相同的范例:查询集只是相同对象的筛选列表。

在我的情况下,我试图让管理员绘制一个多选表单,而不是使用用户名作为文本部分,我想使用我的帐户类中的name字段。

以下是我所得到的细节:

# models.py
class Account(models.Model):
    name = models.CharField(max_length=128,help_text="A display name that people understand")
    user = models.ForeignKey(User, unique=True) # Tied to the User class in settings.py

class Organisation(models.Model):
    administrators = models.ManyToManyField(User)


# admin.py
from django.forms import ModelMultipleChoiceField
from django.contrib.auth.models import User

class OrganisationAdminForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        from ethico.accounts.models import Account
        self.base_fields["administrators"] = ModelMultipleChoiceField(
            queryset=User.objects.all(),
            required=False
        )
        super(OrganisationAdminForm, self).__init__(*args, **kwargs)

class Meta:
    model = Organisation

但是,我希望上面的queryset绘制一个具有Account.name属性和User.id属性的选择框。这不起作用:

queryset=Account.objects.all().order_by("name").values_list("user","name")

此错误失败:

'tuple' object has no attribute 'pk'

我认为这很容易,但它变成了几个小时的死胡同。有人想照亮一点吗?

3 个答案:

答案 0 :(得分:1)

您可以使用自定义窗口小部件,覆盖其render方法。这是我为文本字段所做的事情:

class UserToAccount(forms.widgets.TextInput):
    def render(self, name, value, attrs=None):
        if isinstance(value, User) :
            value = Account.objects.get(user=value).name
        return super (UserToAccount, self).render(name, value, attrs=None)        

然后,当然,使用管理员字段的widget参数,以便使用自定义窗口小部件。 我不知道它是否适合select,但你可以试试。

答案 1 :(得分:0)

查询集需要是一个QuerySet,当你执行values_list时,你会得到一个列表,这样就无法工作。

如果您想更改模型的默认显示,只需覆盖__unicode__即可。见http://docs.djangoproject.com/en/dev/ref/models/instances/#unicode

例如:

def __unicode__(self):
    return u"%s for %s" % (self.name, self.user)

Django会在您要求它打印模型时使用__unicode__。对于测试,您只需在shell中加载模型并执行print my_instance

答案 2 :(得分:0)

从sebpiq排队,我设法弄明白了:

class OrganisationAdminForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):

        from django.forms import MultipleChoiceField
        from ethico.accounts.models import Account

        self.base_fields["administrators"] = MultipleChoiceField(
            choices=tuple([(a.user_id, a.name) for a in Account.objects.all().order_by("name")]),
            widget=forms.widgets.SelectMultiple,
            required=False
        )

        super(OrganisationAdminForm, self).__init__(*args, **kwargs)

    class Meta:
        model = Organisation


class OrganisationAdmin(admin.ModelAdmin):
    form = OrganisationAdminForm


admin.site.register(Organisation, OrganisationAdmin)

关键是放弃了查询集。一旦我使用固定的choices=参数,一切正常。谢谢大家!