Skip to content

Commit

Permalink
SIANXKE-380: prepare option to disable single attachments in admin in…
Browse files Browse the repository at this point in the history
…lines
  • Loading branch information
anx-abruckner committed Nov 29, 2024
1 parent 962050f commit 66b344f
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 2 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,46 @@ class PhotoAlbumAdmin(admin.ModelAdmin):
`ReadOnlyAttachmentInlineAdmin` is useful when attachments should be provided only by REST API. You may consider
extending the classes in order to handle additional permission checks.

The package provides a custom `DynamicallyDisabledAttachmentInlineForm` that allows disablement (setting readonly) of
single attachments depending on its `disable_inline_fields` method. Override it to define your own logic to decide when
an inline attachment should not be editable.
In addition to that a custom `DynamicallyDisabledAttachmentInlineFormSet` class can also disable the DELETE checkbox
of single attachments.

Example usage:
```
# customize the DynamicallyDisabledAttachmentInlineForm to determine which inline attachments should be readonly
MyCustomDynamicallyDisabledAttachmentInlineForm(DynamicallyDisabledAttachmentInlineForm):
def disable_inline_fields(self):
"""
Attachments with context IMMUTABLE should be disabled / readonly
"""
return self.instance and self.instance.context == "IMMUTABLE"
# customize the DynamicallyDisabledAttachmentInlineFormSet to determine which inline attachments' DELETE checkbox
# should be readonly
MyCustomDynamicallyDisabledAttachmentInlineFormSet(DynamicallyDisabledAttachmentInlineFormSet):
super().add_fields(form, index)
"""
DELETE checkbox for Attachments that return True for
MyCustomDynamicallyDisabledAttachmentInlineForm's disable_inline_fields method should be disabled
"""
if hasattr(form, 'disable_inline_fields') and form.disable_inline_fields():
form.fields['DELETE'].disabled = True
class MyCustomDynamicallyDisabledAttachmentInlineAdmin(AttachmentInlineAdmin):
form = MyCustomDynamicallyDisabledAttachmentInlineForm
formset = MyCustomDynamicallyDisabledAttachmentInlineFormSet
def has_add_permission(self, request, obj=None):
return False
show_change_link = False
```


## Usage with DRF (ToDo: API needs to be simplified)


Expand Down
65 changes: 63 additions & 2 deletions drf_attachments/admin.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from content_disposition import rfc5987_content_disposition
from django.contrib import admin
from django.contrib.admin import AdminSite
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib.contenttypes.forms import BaseGenericInlineFormSet
from django.forms import ChoiceField, ModelForm
from django.forms.utils import ErrorList
from django.http import StreamingHttpResponse
from django.urls import NoReverseMatch, path, reverse
from django.utils.safestring import mark_safe
Expand Down Expand Up @@ -117,6 +117,65 @@ def download_view(self, request, object_id):
return response


class DynamicallyDisabledAttachmentInlineForm(AttachmentForm):
class Meta:
model = Attachment
fields = "__all__"

def disable_inline_fields(self):
"""
Override to return True/False when custom condition is met
and change field readonly status in inline admin list on True
"""
raise NotImplementedError()

def __init__(
self,
data=None,
files=None,
auto_id="id_%s",
prefix=None,
initial=None,
error_class=ErrorList,
label_suffix=None,
empty_permitted=False,
instance=None,
use_required_attribute=None,
renderer=None,
):
super().__init__(
data,
files,
auto_id,
prefix,
initial,
error_class,
label_suffix,
empty_permitted,
instance,
use_required_attribute,
renderer,
)

# make all fields of the inline attachment read only
if self.disable_inline_fields():
for field in self.fields:
self.fields[field].disabled = True


class DynamicallyDisabledAttachmentInlineFormSet(BaseGenericInlineFormSet):
def add_fields(self, form, index):
"""
Override to disable the DELETE checkbox of entries matching a specific custom condition.
E.g. to make this dependent of the DynamicallyDisabledAttachmentInlineForm's disable_inline_fields method:
super().add_fields(form, index)
if hasattr(form, 'disable_inline_fields') and form.disable_inline_fields():
form.fields['DELETE'].disabled = True
"""
raise NotImplementedError()


class BaseAttachmentInlineAdmin(GenericTabularInline, AttachmentAdminMixin):
model = Attachment
form = AttachmentForm
Expand All @@ -129,12 +188,14 @@ class BaseAttachmentInlineAdmin(GenericTabularInline, AttachmentAdminMixin):
"mime_type",
"extension",
"creation_date",
"last_modification_date",
)
readonly_fields = (
"size",
"mime_type",
"extension",
"creation_date",
"last_modification_date",
)


Expand Down

0 comments on commit 66b344f

Please sign in to comment.