Skip to content

Commit

Permalink
Merge pull request #76 from globophobe/feature/django-import-export
Browse files Browse the repository at this point in the history
Add integration with django-import-export
  • Loading branch information
globophobe authored Jan 3, 2024
2 parents 6ba77b3 + 5553b64 commit 54f5aaa
Show file tree
Hide file tree
Showing 32 changed files with 1,168 additions and 412 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ INSTALLED_APPS = [
]
```

Please remember to run `python manage.py collectstatic` for production deployments.

Usage
-----

Expand Down Expand Up @@ -104,6 +106,28 @@ class DemoModel(models.Model):
return format_html(html)
```

3. Optional integration with [django-import-export](https://github.com/django-import-export/django-import-export):

<img src="https://raw.githubusercontent.com/globophobe/django-semantic-admin/master/docs/screenshots/django-import-export.png" width="670" alt="django-import-export" />

To enable this awesome feature, instead of `import_export.ImportExportModelAdmin`, etc:

```python
from import_export.admin import ImportExportModelAdmin

class ExampleImportExportAdmin(ImportExportModelAdmin):
pass
```

Inherit from their `Semantic` equivalents:

```python
from semantic_admin.contrib.import_export.admin import SemanticImportExportModelAdmin

class ExampleImportExportAdmin(SemanticImportExportModelAdmin):
pass
```

Contributing
------------

Expand Down
61 changes: 45 additions & 16 deletions demo/demo_app/admin.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
from typing import Optional

from django.conf import settings
from django.contrib import admin
from django.contrib.admin import ModelAdmin as DefaultModelAdmin
from django.contrib.admin import StackedInline as DefaultStackedInline
from django.contrib.admin import TabularInline as DefaultTabularInline
from django.contrib.auth.models import Group, User
from django.db.models import Count
from django.db.models import Count, QuerySet
from django.http import HttpRequest
from django.urls import reverse
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from taggit.models import Tag

from semantic_admin import (
SemanticModelAdmin,
SemanticStackedInline,
SemanticTabularInline,
)
from taggit.models import Tag

from .filters import PersonFilter
from .models import Favorite, Person, Picture
Expand All @@ -38,14 +42,17 @@
TabularInline = DefaultTabularInline


def html5_picture(obj, css=""):
def html5_picture(obj: Picture, css: str = "") -> str:
"""HTML5 picture."""
name = str(obj)
img = obj.get_img(css=css)
html = f"{img}<em>{name}</em>"
return format_html(mark_safe(html))


class PictureStackedInline(StackedInline):
"""Picture stacked inline."""

model = Picture
fields = (
("date_and_time", "tags"),
Expand All @@ -56,23 +63,31 @@ class PictureStackedInline(StackedInline):
show_change_link = True
extra = 0

def inline_picture(self, obj):
def inline_picture(self, obj: Picture) -> str:
"""Inline picture."""
return html5_picture(obj, css="large rounded")

inline_picture.short_description = _("picture").capitalize() # type: ignore

def has_add_permission(self, request, obj=None):
def has_add_permission(
self, request: HttpRequest, obj: Optional[Picture] = None
) -> bool:
"""Has add permission."""
return False


class PersonFavoriteTabularInline(TabularInline):
"""Person favorite tabular inline."""

model = Favorite
autocomplete_fields = fields = ("picture",)
extra = 0


@admin.register(Person)
class PersonAdmin(ModelAdmin):
"""Person admin."""

search_fields = ("name",)
filterset_class = PersonFilter
list_display = ("name", "birthday", "list_friends", "list_favorites")
Expand All @@ -88,7 +103,8 @@ class PersonAdmin(ModelAdmin):
actions = ("send_friend_request",)
inlines = (PictureStackedInline, PersonFavoriteTabularInline)

def list_friends(self, obj):
def list_friends(self, obj: Person) -> str:
"""List friends."""
friends = []
for friend in obj.friends.all():
url = reverse("admin:demo_app_person_change", args=(friend.pk,))
Expand All @@ -99,7 +115,8 @@ def list_friends(self, obj):

list_friends.short_description = _("friends").capitalize() # type: ignore

def list_favorites(self, obj):
def list_favorites(self, obj: Person) -> str:
"""List favorites."""
favorites = []
for favorite in obj.favorites.all():
picture = favorite.picture
Expand All @@ -113,24 +130,30 @@ def list_favorites(self, obj):

list_favorites.short_description = _("favorites").capitalize() # type: ignore

def send_friend_request(self, request, queryset):
def send_friend_request(self, request: HttpRequest, queryset: QuerySet) -> None:
"""Send friend request."""
msg = _("You are now friends with {friends}.")
format_dict = {"friends": ", ".join((obj.name for obj in queryset))}
format_dict = {"friends": ", ".join(obj.name for obj in queryset)}
self.message_user(request, msg.format(**format_dict))

def get_queryset(self, request):
def get_queryset(self, request: HttpRequest) -> QuerySet:
"""Get queryset."""
queryset = super().get_queryset(request)
return queryset.prefetch_related("friends", "favorites__picture")


class PictureFavoriteTabularInline(TabularInline):
"""Picture favorite tabular inline."""

model = Favorite
autocomplete_fields = fields = ("person",)
extra = 0


@admin.register(Picture)
class PictureAdmin(ModelAdmin):
"""Picture admin."""

search_fields = ("tags__name",)
list_filter = ("person",)
list_display = (
Expand Down Expand Up @@ -159,36 +182,42 @@ class PictureAdmin(ModelAdmin):
list_per_page = 10
inlines = (PictureFavoriteTabularInline,)

def list_picture(self, obj):
def list_picture(self, obj: Picture) -> str:
"""List picture."""
return html5_picture(obj, css="medium rounded")

list_picture.short_description = _("picture").capitalize() # type: ignore
list_picture.admin_order_field = "date_and_time" # type: ignore

def detail_picture(self, obj):
def detail_picture(self, obj: Picture) -> str:
"""Detail picture."""
return html5_picture(obj, css="large rounded")

detail_picture.short_description = _("picture").capitalize() # type: ignore

def person_changelink(self, obj):
def person_changelink(self, obj: Picture) -> str:
"""Person change link."""
url = reverse("admin:demo_app_person_change", args=(obj.pk,))
a = f"<a href={url}>{obj.person.name}</a>"
return format_html(mark_safe(a))

person_changelink.short_description = _("person").capitalize() # type: ignore
person_changelink.admin_order_field = "person" # type: ignore

def has_favorites(self, obj):
def has_favorites(self, obj: Picture) -> bool:
"""Has favorites."""
return obj.total_favorites > 1

has_favorites.short_description = _("has favorites").capitalize() # type: ignore
has_favorites.admin_order_field = "total_favorites"
has_favorites.boolean = True # type: ignore

def has_add_permission(self, request):
def has_add_permission(self, request: HttpRequest) -> bool:
"""Has add permission."""
return False

def get_queryset(self, request):
def get_queryset(self, request: HttpRequest) -> QuerySet:
"""Get queryset."""
queryset = super().get_queryset(request)
queryset = queryset.select_related("person")
queryset = queryset.prefetch_related("tags")
Expand Down
Loading

0 comments on commit 54f5aaa

Please sign in to comment.