Django 관리 화면에서 "다른 추가"를 제거하십시오
-
19-09-2019 - |
문제
Object B에 대한 외국 키로 객체 A를 편집 할 때마다 객체 B의 선택 옆에 "Add Alth"를 사용할 수 있습니다. 해당 옵션을 제거하려면 어떻게해야합니까?
객체 B를 추가 할 권한이없는 사용자를 구성했습니다. Plus 부호는 여전히 사용할 수 있지만 클릭하면 "권한 거부"라고 표시됩니다. 못 생겼어.
Django 1.0.2를 사용하고 있습니다
해결책
감가 상각 된 답변
장고는 이후 이것을 가능하게했다.
대신 CSS를 사용하여 단순히 버튼을 표시하지 않는 것을 고려해 보셨습니까? 어쩌면 너무 해킹 될 수도 있습니다.
이것은 테스트되지 않았지만 생각하고 있습니다 ...
아드 다이나 로저-버튼 .CSS
#_addanother { display: none }
admin.py
class YourAdmin(admin.ModelAdmin):
# ...
class Media:
# edit this path to wherever
css = { 'all' : ('css/no-addanother-button.css',) }
이 작업을 수행 한 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',) }
다른 팁
(이 잘못된 대답을 멈추지 마세요 !!!)
정오표 :이 답변은 기본적으로 잘못되었으며 OP의 질문에 대답하지 않습니다. 아래를 참조하십시오.
(이것은 OP가 요청한 것처럼 외국 키 필드가 아니라 인라인 형태에만 적용됩니다)
더 간단한 솔루션, CSS 해킹 없음, 편집 Django 코드베이스 :
인라인 클래스에 이것을 추가하십시오.
max_num=0
업데이트
이것은 OP의 질문에 대답하지 않으며 요청 된대로 외국 키가 아니라 인라인 형식의 "관련"버튼을 숨기는 데 유용합니다.
내가이 답을 썼을 때, IIRC가 받아 들여진 답변은 둘 다 숨기므로 혼란스러워졌습니다.
다음 링크는 솔루션을 제공하는 것으로 보입니다 (CSS를 사용하는 숨기는 것이 가장 실현 가능한 것 같습니다. 특히 인라인 형태의 "다른 추가"버튼이있는 경우 :
여기에 언급 된 대부분의 솔루션이 작동하지만 더 깨끗한 방법이 있습니다. 아마도 다른 솔루션이 발표 된 후 후기 버전의 Django에서 소개되었을 것입니다. (저는 현재 Django 1.7을 사용하고 있습니다)
"다른 추가"옵션을 제거하려면
class ... #(Your inline class)
def has_add_permission(self, request):
return False
마찬가지로 "삭제"를 비활성화하려면? 옵션, 인라인 클래스에 다음 방법을 추가하십시오.
def has_delete_permission(self, request, obj=None):
return False
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
여기에서 변화를 만드는 흥미로운 부분 get_form
그게 다 author.widget
인스턴스입니다 django.contrib.admin.widgets.RelatedFieldWidgetWrapper
마치 중 하나를 시도하고 변경하는 것처럼 formfield_for_xxxxx
함수, 위젯은 실제 양식 위젯의 인스턴스입니다.이 일반적인 외국 키 케이스에서는 django.forms.widgets.Select
.
보다 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)
최선의 방법은 서브 클래스를 만드는 것이라고 생각합니다 ModelAdmin
(결국 서브 클래스입니다 BaseModelAdmin
), 새로운 클래스에 대한 모델을 기준으로 formfield_fo_dbfield
그리고 그것이 위젯을 조건부로 감싸지 않도록하십시오. RelatedFieldWidgetWrapper
.
관련 객체를 추가 할 권한이없는 사용자가있는 경우 RelatedFieldWidgetWrapper
추가 링크를 표시하지 않아야합니까? 어쩌면 이것은 언급 할 가치가있는 것입니다. Django Trac?
나는 다음 접근법을 사용합니다 형태 그리고 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
인라인 형태
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
답변 @SlipStream 쇼 어떻게 솔루션을 구현하려면 viz. Formfield의 위젯의 속성을 무시함으로써, 그러나 제 생각에는 get_form
이것을하기에 가장 논리적 인 장소는 아닙니다.
답변 @Cethegeek 쇼 어디 솔루션을 구현하려면 viz. 연장에서 formfield_for_dbfield
, 그러나 명시적인 예를 제공하지는 않습니다.
왜 사용 formfield_for_dbfield
? 그것의 Docstring 양식 필드를 엉망으로 만들기위한 지정된 후크라고 제안합니다.
주어진 데이터베이스 필드 인스턴스의 양식 필드 인스턴스를 지정하려면 후크.
또한 (약간) 클리너 및 명확한 코드를 허용하고 보너스로 추가 양식을 쉽게 설정할 수 있습니다. Field
속성, 와 같은 initial
가치 및/또는 disabled
(예시 여기), 그것들을 추가함으로써 kwargs
(전화하기 전에 super
).
따라서 두 가지 답변을 결합합니다 (OP의 모델이 ModelA
그리고 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)
참고 : 인 경우 ForeignKey
모델 필드가 있습니다 on_delete=models.CASCADE
,, can_delete_related
속성입니다 False
기본적으로, 원천 ~을 위한 RelatedFieldWidgetWrapper
.
나는 django 2.x를 사용하고 있으며 적어도 내 경우에는 최상의 솔루션을 찾았다 고 생각합니다.
"저장 및 다른 추가"버튼에 HTML 파일이 켜져 있습니다. your_python_installation\Lib\site-packages\django\contrib\admin\templates\admin\subtmit_line.html
.
- 해당 HTML 파일을 복사하여 프로젝트에 페이팅하십시오.
your_project\templates\admin\submit_line.html
. - 원하는대로 버튼 코드를 주석/삭제하십시오.
{#{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" />{% endif %}#}
이 문제가 이미 답변된다는 것을 알고 있습니다. 그러나 미래의 누군가가 나와 비슷한 경우를 가지고있을 것입니다.
Cethegeek 답변을 기반으로 나는 이것을 만들었다 :
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
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')))