Наткнувшись недавно на статью о react-admin, я решил попробовать что это за зверь. Было интересно прикрутить это к джанге, благо там есть dataprovider для rest framework.
Но сначала нужно представить админку в виде api. В принципе, это легко делается с помощью viewset`ов, которых можно нагенерить автоматически пройдясь по моделям из админки.
def get_serializer_class(model):
return type(
f"{model.__name__}Serializer",
(ModelSerializer,),
{"Meta": type("Meta", (), {"model": model, "fields": "__all__"})},
)
for model, model_admin in admin.site._registry.items():
params = {
"queryset": model.objects.all(),
"filter_backends": [DjangoFilterBackend, OrderingFilter],
"info": action(methods=["get"], detail=False)(get_info(model_admin)),
"serializer_class": get_serializer_class(model),
"basename": model._meta.model_name,
"request": r,
"fields": list(model_admin.get_fields(r)),
"list_display": list(model_admin.get_list_display(r)),
"ordering_fields": list(model_admin.get_sortable_by(r)),
"filterset_fields": list(model_admin.get_list_filter(r)),
"permission_classes": [permissions.IsAdminUser, permissions.DjangoModelPermissions],
"pagination_class": CustomPageNumberPagination
}
viewset = type(f"{model.__name__}ViewSet", (viewsets.ModelViewSet,), params)
router.register(
f"{model._meta.app_label}/{model._meta.model_name}", viewset
)
Даже разграничение прав работает из коробки!
react-admin работает практически из коробки. Благодаря ListGuesser, EditGuesser, etc формы создаются автоматически.
Хотелось бы сделать их более близкими к модели на основе данных из drf options, но сходу разобраться не удалось, оставил задачку на потом(pull requests are welcome).
Чтобы было удобно собирать статику для фронта я сделал небольшую management command`у
import subprocess, os, sys
from django.core.management.base import BaseCommand
from django.core import management
class Command(BaseCommand):
help = 'Build react-admin'
def handle(self, *args, **options):
cwd = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../src')
ps = subprocess.Popen("yarn install", shell=True, cwd=cwd)
ps.wait() and sys.exit(1)
ps = subprocess.Popen("yarn build", shell=True, cwd=cwd)
ps.wait() and sys.exit(1)
management.call_command('collectstatic')
Чтобы попробовать достаточно добавить 'django_react_admin' в INSTALLED_APPS и добавить urls:
from django_react_admin import urls
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('react_admin/', include(urls.urlpatterns)),
]
Сам проект: github.com/pawnhearts/django_react_admin
Вообще админка в виде api это очень полезно. Можно, например, сделать мобильное приложение на nativescript.
Автор: pawnhearts