Skip to content

Commit

Permalink
Merge pull request #1 from anexia-it/refactoring-context
Browse files Browse the repository at this point in the history
Make translatable context optional, extend readme for django admin case
  • Loading branch information
anx-abruckner authored Feb 16, 2022
2 parents 3de3d1e + eeb1b06 commit 188d76b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 24 deletions.
47 changes: 39 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# DRF Attachments

Django rest framework module to manage any model's file up-/downloads by relating an Attachment model to it.
Django module to manage any model's file up-/downloads by relating an Attachment model to it.
The module can be used for extending the Django Admin or for exposing the attachment via Django REST Framework.

## Installation
## Installation and Setup

1. Install using pip:

Expand All @@ -20,7 +21,37 @@ INSTALLED_APPS = [
]
```

3. Add a helper/utils file to your project's source code (e.g. `attachments.py`) and prepare the methods `attachment_content_object_field`, `attachment_context_translatables`, `filter_viewable_content_types`, `filter_editable_content_types` and `filter_deletable_content_types` there.
## Usage with Django Admin

1. Add minimal settings

```python
# drf-attachment settings
ATTACHMENT_MAX_UPLOAD_SIZE = 1024 * 1024 * 25
ATTACHMENT_CONTEXT_CONTEXT_1 = "CONTEXT-1"
ATTACHMENT_CONTEXT_CONTEXT_2 = "CONTEXT-2"
```

2. Add `AttachmentInlineAdmin` or `ReadOnlyAttachmentInlineAdmin` to each model that needs attachment

```python
from django.contrib import admin
from drf_attachments.admin import AttachmentInlineAdmin

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
inlines = [
AttachmentInlineAdmin,
]
```

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

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


1. Add a helper/utils file to your project's source code (e.g. `attachments.py`) and prepare the methods `attachment_content_object_field`, `attachment_context_translatables`, `filter_viewable_content_types`, `filter_editable_content_types` and `filter_deletable_content_types` there.

```
# within app/your_app_name/attachments.py
Expand Down Expand Up @@ -62,22 +93,22 @@ def filter_deletable_content_types(queryset):
```

4. Define the helper/utils methods' paths within your `settings.py` as `ATTACHMENT_CONTENT_OBJECT_FIELD_CALLABLE` and `ATTACHMENT_CONTEXT_TRANSLATABLES_CALLABLE`:
2. Define the helper/utils methods' paths within your `settings.py` as `ATTACHMENT_CONTENT_OBJECT_FIELD_CALLABLE` and `ATTACHMENT_CONTEXT_TRANSLATABLES_CALLABLE`:
```
# within settings.py
ATTACHMENT_CONTENT_OBJECT_FIELD_CALLABLE = "your_app_name.attachments.attachment_content_object_field"
ATTACHMENT_CONTEXT_TRANSLATABLES_CALLABLE = "your_app_name.attachments.attachment_context_translatables"
```

5. Add the `ATTACHMENT_MAX_UPLOAD_SIZE` to your `settings.py`:
3. Add the `ATTACHMENT_MAX_UPLOAD_SIZE` to your `settings.py`:
```
# within settings.py
ATTACHMENT_MAX_UPLOAD_SIZE = env.int("ATTACHMENT_MAX_UPLOAD_SIZE", default=1024 * 1024 * 25)
```

6. Define any context choices your attachment files might represent (e.g. "driver's license", "offer", "contract", ...) as `ATTACHMENT_CONTEXT_CHOICES` in the `settings.py`. We recommend defining each context type as constant before adding them to the "choices" dict, e.g.:
4. Define any context choices your attachment files might represent (e.g. "driver's license", "offer", "contract", ...) as `ATTACHMENT_CONTEXT_CHOICES` in the `settings.py`. We recommend defining each context type as constant before adding them to the "choices" dict, e.g.:
```
# within settings.py
Expand All @@ -87,14 +118,14 @@ ATTACHMENT_CONTEXT_CONTRACT = 'CONTRACT'
ATTACHMENT_CONTEXT_OTHER = 'OTHER'
```

7. Optionally define a default context in the `settings.py` that will be set automatically each time you save an attachment without explicitly defining a context yourself, e.g.:
5. Optionally define a default context in the `settings.py` that will be set automatically each time you save an attachment without explicitly defining a context yourself, e.g.:
```
# within settings.py
...
ATTACHMENT_DEFAULT_CONTEXT = 'ATTACHMENT'
```

8. Add all possible context choices (and the default value, if defined) to the `attachment_context_translatables` method to make them translatable and detectable via the `makemessages` command, e.g.:
6. Add all possible context choices (and the default value, if defined) to the `attachment_context_translatables` method to make them translatable and detectable via the `makemessages` command, e.g.:
```
# within app/your_app_name/attachments.py
Expand Down
28 changes: 15 additions & 13 deletions drf_attachments/admin.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline
from django.forms import ChoiceField, ModelForm
from django.forms.utils import ErrorList
from django.utils.translation import ugettext_lazy as _

from drf_attachments.models.models import Attachment, attachment_context_choices, attachment_context_translatable
from drf_attachments.models.models import Attachment, attachment_context_choices

__all__ = [
"AttachmentInlineAdmin",
Expand Down Expand Up @@ -51,33 +49,37 @@ class AttachmentAdmin(admin.ModelAdmin, AttachmentAdminMixin):
)


class AttachmentInlineAdmin(GenericTabularInline, AttachmentAdminMixin):
class BaseAttachmentInlineAdmin(GenericTabularInline, AttachmentAdminMixin):
model = Attachment
extra = 0
fields = (
"context_label",
"name",
"download_url",
"file",
"size",
"mime_type",
"extension",
"creation_date",
)
readonly_fields = (
"context_label",
"name",
"download_url",
"file",
"size",
"mime_type",
"extension",
"creation_date",
)
show_change_link = False

class Media:
css = {"": ("attachments/attachment_admin.css",)}


class AttachmentInlineAdmin(BaseAttachmentInlineAdmin):
def has_change_permission(self, request, obj=None):
return False

show_change_link = True


class ReadOnlyAttachmentInlineAdmin(AttachmentInlineAdmin):
def has_add_permission(self, request, obj=None):
return False

class Media:
css = {"": ("attachments/attachment_admin.css",)}
show_change_link = False
9 changes: 6 additions & 3 deletions drf_attachments/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ def __init__(self):


def get_context_translatables():
module_name, callable_name = settings.ATTACHMENT_CONTEXT_TRANSLATABLES_CALLABLE.rsplit('.', maxsplit=1)
backend_module = importlib.import_module(module_name)
return getattr(backend_module, callable_name)()
context_translatables_callable = getattr(settings, "ATTACHMENT_CONTEXT_TRANSLATABLES_CALLABLE", None)
if context_translatables_callable:
module_name, callable_name = settings.ATTACHMENT_CONTEXT_TRANSLATABLES_CALLABLE.rsplit('.', maxsplit=1)
backend_module = importlib.import_module(module_name)
return getattr(backend_module, callable_name)()
return {}


def attachment_upload_path(attachment, filename):
Expand Down

0 comments on commit 188d76b

Please sign in to comment.