Jac*_* Ha 27 python django django-admin
每当我用对象B的外键编辑对象A时,对象B的选项旁边就会出现加号选项"添加另一个".如何删除该选项?
我配置了一个没有添加对象B权限的用户.加号仍然可用,但是当我点击它时,它会显示"权限被拒绝".它很丑.
我正在使用Django 1.0.2
pis*_*che 49
(停止支持这个错误的答案!)
ERRATA:这个答案基本上是错误的,并没有回答OP的问题.见下文.
(这仅适用于内联表单,而不适用于OP要求的外键字段)
更简单的解决方案,没有CSS黑客,没有编辑Django代码库:
将其添加到您的Inline类:
max_num=0
UPDATE
这不符合OP的问题,只对隐藏内联表单的"添加相关"按钮,而不是按要求隐藏外键.
当我写这个答案时,IIRC接受的答案都隐藏了,这就是为什么我感到困惑.
以下链接似乎提供了一个解决方案(虽然使用CSS隐藏似乎是最可行的事情,特别是如果在内联表单中添加FK的"另一个"按钮):
Sud*_*pta 25
虽然这里提到的大部分解决方案都有效,但还有另一种更清洁的方法.在提出其他解决方案之后,可能是在Django的更高版本中引入的.(我现在正在使用Django 1.7)
要删除"添加其他"选项,
class ... #(Your inline class)
def has_add_permission(self, request):
return False
Run Code Online (Sandbox Code Playgroud)
同样,如果要禁用"删除?" 选项,在Inline类中添加以下方法.
def has_delete_permission(self, request, obj=None):
return False
Run Code Online (Sandbox Code Playgroud)
End*_*age 13
NB适用于DJango 1.5.2且可能更老.该can_add_related
物业出现在大约2年前.
我发现的最好方法是覆盖ModelAdmin的get_form函数.在我的情况下,我想强迫帖子的作者成为当前登录的用户.代码如下,附有大量评论.真正重要的是设置widget.can_add_related
:
def get_form(self,request, obj=None, **kwargs):
# get base form object
form = super(BlogPostAdmin,self).get_form(request, obj, **kwargs)
# get the foreign key field I want to restrict
author = form.base_fields["author"]
# remove the green + by setting can_add_related to False on the widget
author.widget.can_add_related = False
# restrict queryset for field to just the current user
author.queryset = User.objects.filter(pk=request.user.pk)
# set the initial value of the field to current user. Redundant as there will
# only be one option anyway.
author.initial = request.user.pk
# set the field's empty_label to None to remove the "------" null
# field from the select.
author.empty_label = None
# return our now modified form.
return form
Run Code Online (Sandbox Code Playgroud)
在这里进行更改的有趣部分get_form
是,这author.widget
是一个实例,django.contrib.admin.widgets.RelatedFieldWidgetWrapper
如果您尝试在其中一个formfield_for_xxxxx
函数中进行更改,则窗口小部件是实际窗体窗口小部件的实例,在此典型的ForeignKey情况下,它是a django.forms.widgets.Select
.
@Slipstream的答案显示了如何实施解决方案,即。通过覆盖表单域小部件的属性,但在我看来,get_form
这不是最合乎逻辑的地方。
@cethegeek的答案显示了在哪里实施解决方案,即。在 的扩展中formfield_for_dbfield
,但没有提供明确的例子。
为什么使用formfield_for_dbfield
?它的文档字符串表明它是用于处理表单字段的指定钩子:
用于为给定数据库 Field 实例指定表单 Field 实例的挂钩。
它还允许(稍微)更清晰和更清晰的代码,作为奖励,我们可以通过将它们添加到(在调用之前)轻松设置额外的表单Field
属性,例如initial
值和/或disabled
(此处的示例)。kwargs
super
因此,结合两个答案(假设 OP 的模型是ModelA
and ModelB
,并且ForeignKey
模型字段名为b
):
class ModelAAdmin(admin.ModelAdmin):
def formfield_for_dbfield(self, db_field, request, **kwargs):
# optionally set Field attributes here, by adding them to kwargs
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
if db_field.name == 'b':
formfield.widget.can_add_related = False
formfield.widget.can_change_related = False
formfield.widget.can_delete_related = False
return formfield
# Don't forget to register...
admin.site.register(ModelA, ModelAAdmin)
Run Code Online (Sandbox Code Playgroud)
注意:如果ForeignKey
模型字段on_delete=models.CASCADE
,该can_delete_related
属性是False
在默认情况下,如能在可以看到源的RelatedFieldWidgetWrapper
。
查看django.contrib.admin.options.py
并查看BaseModelAdmin
课程,formfield_for_dbfield
方法.
你会看到这个:
# For non-raw_id fields, wrap the widget with a wrapper that adds
# extra HTML -- the "add other" interface -- to the end of the
# rendered output. formfield can be None if it came from a
# OneToOneField with parent_link=True or a M2M intermediary.
if formfield and db_field.name not in self.raw_id_fields:
formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site)
Run Code Online (Sandbox Code Playgroud)
我认为最好的选择是创建子类ModelAdmin
(后者又是其子类BaseModelAdmin
),将模型基于该新类,重写formfield_fo_dbfield
并使其成为不会/或将有条件地包装小部件RelatedFieldWidgetWrapper
.
有人可能会说,如果您的用户无权添加相关对象,则RelatedFieldWidgetWrapper
不应显示添加链接?也许这是Django trac值得一提的东西?
我对Form和InlineForm使用以下方法
Django 2.0,Python 3+
形成
class MyModelAdmin(admin.ModelAdmin):
#...
def get_form(self,request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
user = form.base_fields["user"]
user.widget.can_add_related = False
user.widget.can_delete_related = False
user.widget.can_change_related = False
return form
Run Code Online (Sandbox Code Playgroud)
内联表格
class MyModelInline(admin.TabularInline):
#...
def get_formset(self, request, obj=None, **kwargs):
formset = super().get_formset(request, obj, **kwargs)
user = formset.form.base_fields['user']
user.widget.can_add_related = False
user.widget.can_delete_related = False
user.widget.can_change_related = False
return formset
Run Code Online (Sandbox Code Playgroud)
Django 使这一切成为可能。
您是否考虑过使用 CSS 来简单地不显示按钮?也许这有点太老套了。
这是未经测试的,但我在想......
no-addanother-button.css
#_addanother { display: none }
Run Code Online (Sandbox Code Playgroud)
admin.py
class YourAdmin(admin.ModelAdmin):
# ...
class Media:
# edit this path to wherever
css = { 'all' : ('css/no-addanother-button.css',) }
Run Code Online (Sandbox Code Playgroud)
用于执行此操作的 Django Doc——媒体作为静态定义
注意/编辑:文档说文件将以 MEDIA_URL 开头,但在我的实验中并非如此。你的旅费可能会改变。
如果您发现您遇到这种情况,可以快速解决此问题...
class YourAdmin(admin.ModelAdmin):
# ...
class Media:
from django.conf import settings
media_url = getattr(settings, 'MEDIA_URL', '/media/')
# edit this path to wherever
css = { 'all' : (media_url+'css/no-addanother-button.css',) }
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17176 次 |
最近记录: |