Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 删除“;加上另一个“;在Django管理屏幕中_Python_Django_Django Admin - Fatal编程技术网

Python 删除“;加上另一个“;在Django管理屏幕中

Python 删除“;加上另一个“;在Django管理屏幕中,python,django,django-admin,Python,Django,Django Admin,每当我使用对象B的外键编辑对象A时,在对象B的选项旁边会有一个加号选项“添加另一个”。如何删除该选项 我配置了一个无权添加对象B的用户。加号仍然可用,但当我单击它时,它会显示“权限被拒绝”。很难看 我正在使用Django 1.0.2查看Django.contrib.admin.options.py并查看BaseModelAdmin类,formfield\u for\u dbfield方法 您将看到: # For non-raw_id fields, wrap the widget with a

每当我使用对象B的外键编辑对象A时,在对象B的选项旁边会有一个加号选项“添加另一个”。如何删除该选项

我配置了一个无权添加对象B的用户。加号仍然可用,但当我单击它时,它会显示“权限被拒绝”。很难看


我正在使用Django 1.0.2

查看
Django.contrib.admin.options.py
并查看
BaseModelAdmin
类,
formfield\u for\u 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)
我认为您最好的选择是创建
ModelAdmin
的子类(它又是
BaseModelAdmin
的子类),将您的模型建立在新类的基础上,重写
formfield\u fo\u dbfield
并使其不/或有条件地将小部件包装在
relatedfieldwiggetwrapper

有人可能会说,如果您的用户没有添加相关对象的权限,
RelatedFieldWidgetWrapper
不应该显示添加链接?也许这是值得一提的?

不赞成的答案 Django使这成为可能


您是否考虑过使用CSS来简单地不显示按钮?也许这有点太老套了

这是未经测试的,但我想

no-addanother-button.css 管理员 Django Doc感谢您这么做--

注意/编辑:文档中说这些文件将在前面加上媒体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',) }

django.contrib.admin.widgets.py

(Django Install Dir)/Django/contrib/admin/widgets.py:注释第239行和第244行之间的所有内容:

 if rel_to in self.admin_site._registry: # If the related object has an admin interface:
        # TODO: "id_" is hard-coded here. This should instead use the correct
        # API to determine the ID dynamically.
        output.append(u'<a href="%s" class="add-another" id="add_id_%s" onclick="return showAddAnotherPopup(this);"> ' % \
            (related_url, name))
        output.append(u'<img src="%simg/admin/icon_addlink.gif" width="10" height="10" alt="%s"/></a>' % (settings.ADMIN_MEDIA_PREFIX, _('Add Another')))
if rel_to in self.admin_site._registry:#如果相关对象具有管理接口:
#TODO:“id_”在这里是硬编码的。这应该使用正确的
#API来动态确定ID。
output.append(u'%(settings.ADMIN\u MEDIA\u前缀,u(‘添加另一个’))
(不要再投票给这个错误的答案了!!!)

勘误表:这个答案基本上是错误的,没有回答OP的问题。见下文

(这仅适用于内联表单,不适用于OP要求的外键字段)

更简单的解决方案,无CSS攻击,无需编辑Django代码库:

将其添加到内联类:

max_num=0

更新

这并没有回答OP的问题,只在隐藏内联表单的“添加相关”按钮时有用,而不是在请求时隐藏外键

当我写这个答案时,被接受的答案隐藏了两者,这就是为什么我感到困惑

下面的链接似乎提供了一个解决方案(尽管使用CSS隐藏似乎是最可行的方法,尤其是在内联表单中FKs的“添加另一个”按钮的情况下):


N.B.适用于DJango 1.5.2及更老版本。大约2年前,
可以添加相关的
属性

我发现最好的方法是重写ModelAdmin的get\u form函数。在我的例子中,我想强制一篇文章的作者成为当前登录的用户。下面的代码包含大量注释。真正重要的一点是
小部件的设置。是否可以添加相关的

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

get_form
中进行更改的有趣部分是
author.widget
django.contrib.admin.widgets.RelatedFieldWidgetWrapper
的一个实例,如果您尝试在其中一个
formfield_中对xxxxx
函数进行更改,则该小部件是实际表单小部件的一个实例,在这个典型的ForeignKey案例中,它是一个
django.forms.widgets.Select

虽然这里提到的大多数解决方案都有效,但还有另一种更干净的方法。可能是在Django的更高版本中,在其他解决方案出现之后引入的。(我目前正在使用Django 1.7)

要删除“添加另一个”选项

类似地,如果要禁用“Delete?”选项,请在内联类中添加以下方法

    def has_delete_permission(self, request, obj=None):
        return False

根据CETHEGEK的回答,我做了以下几点:

class SomeAdmin(admin.ModelAdmin):
    form = SomeForm

    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(SomeAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'some_m2m_field':
            request = kwargs.pop("request", None)
            formfield = self.formfield_for_manytomany(db_field, request, **kwargs)  # for foreignkey: .formfield_for_foreignkey
            wrapper_kwargs = {'can_add_related': False, 'can_change_related': False, 'can_delete_related': False}
            formfield.widget = admin.widgets.RelatedFieldWidgetWrapper(
                formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs
            )
        return formfield

对于表单内联表单

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  
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
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  
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
内联表单

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  
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

我正在使用Django 2.x,我认为我找到了最好的解决方案,至少对我的案例是这样

“保存并添加另一个”按钮的HTML文件位于
您的\u python\u安装\Lib\site packages\django\contrib\admin\templates\admin\submit\u line.HTML

  • 复制该html文件并粘贴到您的项目中,如so
    your\u project\templates\admin\submit\u line.html
  • 打开它并根据需要注释/删除按钮代码:
  • {{%if show{u save}和{u add}{%endif%}}

    我知道这个问题已经解决了。但是也许将来会有人和我有类似的情况。

    的答案显示了如何实现解决方案,即。通过覆盖formfield小部件的属性,但是,在我看来,
    get\u form
    并不是这样做的最合理的地方

    答案显示了在何处实施解决方案,即。在
    formfield\u for_dbfield
    的扩展中,但未提供明确的示例

    为什么要将
    formfield\u用于\u dbfield
    ?它表明它是处理表单字段的指定钩子:

    用于为给定数据库字段实例指定表单字段实例的钩子

    它还允许(稍微)更清晰的代码,作为奖励,我们可以通过将它们添加到
    kwargs
    (在调用
    super
    之前)来轻松设置额外的表单
    字段
    ,例如
    初始值和/或
    禁用值
    (示例)

    因此,结合这两个答案(假设OP的模型a