2017-05-26 42 views
0

我正在为我正在构建的应用程序构建一个配置文件驱动的管理员。用户对层次结构树的某些部分具有某些权限(在管理员表单中显示为select),并且我希望仅在select中显示树的这一部分。我想更改此选择字段的queryset属性。管理员覆盖表单字段属性

表单没有关于请求(用户)的知识,所以我不能在它的__init__中对其进行处理。

我已经尝试在ModelAdmin.get_form()中设置form.base_fields,但是我对此方法有副作用:有些用户可以看到其他用户的树,并且由于权限而有错误消息。要避免这些错误的唯一方法是重新加载项目(在Web服务器级别),这是不是一个选项...

我也试过重写ModelAdmin.get_fields()方法,但它似乎并没有被调用。

有人有关于如何做到这一点的想法?

...我会提供一些代码...

联系:

https://gist.github.com/frague59/f90ba63bb2548fb27e32576329159543

形式:

https://gist.github.com/frague59/aa5236eb11982bd810f81342da8bc05d

回答

0

这听起来像你可能会找方法formfield_for_foreignkey。在文档中的例子显示了如何限制基于用户为字段查询集:

class MyModelAdmin(admin.ModelAdmin): 
    def formfield_for_foreignkey(self, db_field, request, **kwargs): 
     if db_field.name == "car": 
      kwargs["queryset"] = Car.objects.filter(owner=request.user) 
     return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) 
+0

我想更新小部件...但我想我必须在此时重写表单,以提供它的编辑器版本。 – frague

+0

['formfield_overrides'](https://docs.djangoproject.com/en/1.11/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_overrides)选项可让您更改外键的窗口小部件,或如果你可能可以在formfield_for_foreignkey中设置它。我不能提供任何其他建议,因为你没有在你的问题中显示任何代码。 – Alasdair

+0

它不工作。在调试时,我可以看到查询集发生更改,但在表单初始化结束时,表单字段的另一个实例被附加到新表单。 – frague

0

我已经找到一种方法来overrrides的公益领域:在get_form()方法使用deepcopy复制窗体类,然后用base_field更新字段:

class MyAdmin(ModelAdmin): 
    form = MyForm # class ! 
    def get_form(self, ...): 
     self.form = deepcopy(self.form) 
     form = super(MyAdmin, self).get_form(...) 
     if 'foo' in form.base_fields: 
      form.base_fields['foo'].queryset = my_reduced_queryset 
      form.base_fields['foo'].widget = my_pretty_widget 
     ... 
     return form 

感谢您的帮助!