Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dev mode admin + refactor api init #7628

Merged
merged 7 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added ietf/admin/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions ietf/admin/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright The IETF Trust 2024, All Rights Reserved
from django.contrib.admin import apps as admin_apps


class AdminConfig(admin_apps.AdminConfig):
default_site = "ietf.admin.sites.AdminSite"
15 changes: 15 additions & 0 deletions ietf/admin/sites.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright The IETF Trust 2024, All Rights Reserved
from django.contrib.admin import AdminSite as _AdminSite
from django.conf import settings
from django.utils.safestring import mark_safe


class AdminSite(_AdminSite):
site_title = "Datatracker admin"

@staticmethod
def site_header():
if settings.SERVER_MODE == "production":
return "Datatracker administration"
else:
return mark_safe('Datatracker administration <span class="text-danger">&delta;</span>')
43 changes: 17 additions & 26 deletions ietf/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

from urllib.parse import urlencode

from django.conf import settings
from django.apps import apps as django_apps
from django.core.exceptions import ObjectDoesNotExist
from django.utils.module_loading import autodiscover_modules


import debug # pyflakes:ignore

Expand All @@ -19,40 +21,29 @@
from tastypie.exceptions import ApiFieldError
from tastypie.fields import ApiField


_api_list = []

for _app in settings.INSTALLED_APPS:
_module_dict = globals()
if '.' in _app:
_root, _name = _app.split('.', 1)
if _root == 'ietf':
if not '.' in _name:
_api = Api(api_name=_name)
_module_dict[_name] = _api
_api_list.append((_name, _api))

def populate_api_list():
for app_config in django_apps.get_app_configs():
_module_dict = globals()
if '.' in app_config.name:
_root, _name = app_config.name.split('.', 1)
if _root == 'ietf':
if not '.' in _name:
_api = Api(api_name=_name)
_module_dict[_name] = _api
_api_list.append((_name, _api))

def autodiscover():
"""
Auto-discover INSTALLED_APPS resources.py modules and fail silently when
not present. This forces an import on them to register any admin bits they
not present. This forces an import on them to register any resources they
may want.
"""
autodiscover_modules("resources")

from importlib import import_module
from django.conf import settings
from django.utils.module_loading import module_has_submodule

for app in settings.INSTALLED_APPS:
mod = import_module(app)
# Attempt to import the app's admin module.
try:
import_module('%s.resources' % (app, ))
except:
# Decide whether to bubble up this error. If the app just
# doesn't have an admin module, we can ignore the error
# attempting to import it, otherwise we want it to bubble up.
if module_has_submodule(mod, "resources"):
raise

class ModelResource(tastypie.resources.ModelResource):
def generate_cache_key(self, *args, **kwargs):
Expand Down
1 change: 1 addition & 0 deletions ietf/api/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ class Serializer(): ...
class ToOneField(tastypie.fields.ToOneField): ...
class TimedeltaField(tastypie.fields.ApiField): ...

def populate_api_list() -> None: ...
def autodiscover() -> None: ...
15 changes: 15 additions & 0 deletions ietf/api/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.apps import AppConfig
from . import populate_api_list


class ApiConfig(AppConfig):
name = "ietf.api"

def ready(self):
"""Hook to do init after the app registry is fully populated

Importing models or accessing the app registry is ok here, but do not
interact with the database. See
https://docs.djangoproject.com/en/4.2/ref/applications/#django.apps.AppConfig.ready
"""
populate_api_list()
1 change: 1 addition & 0 deletions ietf/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from ietf.submit import views as submit_views
from ietf.utils.urls import url


api.autodiscover()

urlpatterns = [
Expand Down
2 changes: 1 addition & 1 deletion ietf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ def skip_unreadable_post(record):

INSTALLED_APPS = [
# Django apps
'django.contrib.admin',
'ietf.admin', # replaces django.contrib.admin
'django.contrib.admindocs',
'django.contrib.auth',
'django.contrib.contenttypes',
Expand Down
27 changes: 27 additions & 0 deletions ietf/templates/admin/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% extends 'admin/base.html' %}
{% load static %}
{% block extrastyle %}{{ block.super }}
{% if server_mode and server_mode != "production" %}
<style>
{# grab colors that match bootstrap so we don't have to import the css #}
html, :root{
--bs-danger-bg-subtle: #F8D7DAFF;
--bs-danger-text-emphasis: #58151CFF;
--bs-danger: #DC3545FF;
--bs-secondary: #6C757DFF;
--bs-primary-text-emphasis: #052C65FF;
}
html[data-theme="light"], :root {
--primary: var(--bs-danger-bg-subtle);
--secondary: var(--bs-danger-bg-subtle);
--accent: var(--bs-danger-text-emphasis);
--primary-fg: var(--bs-primary-text-emphasis);
--link-fg: var(--bs-danger-text-emphasis);
--header-color: var(--bs-secondary);
--breadcrumbs-fg: var(--bs-secondary);
--breadcrumbs-link-fg: var(--link-fg);
}
span.text-danger { color: var(--bs-danger); }
</style>
{% endif %}
{% endblock %}
2 changes: 0 additions & 2 deletions ietf/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
from ietf.utils.urls import url


admin.autodiscover()

# sometimes, this code gets called more than once, which is an
# that seems impossible to work around.
try:
Expand Down
3 changes: 2 additions & 1 deletion ietf/utils/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import debug # pyflakes:ignore

from ietf.admin.sites import AdminSite
from ietf.person.name import name_parts, unidecode_name
from ietf.submit.tests import submission_file
from ietf.utils.draft import PlaintextDraft, getmeta
Expand Down Expand Up @@ -325,7 +326,7 @@ def test_all_model_admins_exist(self):
User.objects.create_superuser('admin', '[email protected]', 'admin+password')
self.client.login(username='admin', password='admin+password')
rtop = self.client.get("/admin/")
self.assertContains(rtop, 'Django administration')
self.assertContains(rtop, AdminSite.site_header())
for name in self.apps:
app_name = self.apps[name]
self.assertContains(rtop, name)
Expand Down
Loading