Package: privex-adminplus
Privex's Custom Admin for DjangoThis is a custom admin views extension for theDjango Web Framework, which has been
designed as an alternative toDjango AdminPlus.Despite the name, neither this project, nor ourselves have any affiliation with the originalDjango AdminPlus, nor is this project designed to be a 1:1 exact
re-implementation of Django AdminPlus - it may in some cases work as a drop-in replacement, but is not guaranteed
to work like that.+===================================================+
|                 © 2020 Privex Inc.                |
|               https://www.privex.io               |
+===================================================+
|                                                   |
|        Privex Django Admin Plus                   |
|        License: X11/MIT                           |
|                                                   |
|        Core Developer(s):                         |
|                                                   |
|          (+)  Chris (@someguy123) [Privex]        |
|                                                   |
+===================================================+

Privex Django Admin Plus - An extension for Django so you can add custom views to the admin panel
Copyright (c) 2020    Privex Inc. ( https://www.privex.io )Install with pipWe recommend at least Python 3.6 - we cannot guarantee compatibility with older versions.pip3 install privex-adminplusQuickstartInstall theprivex-adminpluspackage from PyPi usingpip3/pipenv# Using the standard 'pip3' package managerpip3install-Uprivex-adminplus# Using 'pipenv' - third party package manager + virtualenv manager + interpreter version managerpipenvinstallprivex-adminplusAdd toINSTALLED_APPSinYourProject/yourapp/settings.pyOpensettings.pyin your Django project.Remove the defaultdjango.contrib.adminfrom INSTALLED_APPS. Then addprivex.adminplusfollowed byprivex.adminplus.apps.PVXAdminto theSTART/TOPofINSTALLED_APPS.INSTALLED_APPS=[# You must delete / comment out the line for the default admin (django.contrib.admin)# 'django.contrib.admin',# NOTE: If you are running a version of Django older than 3.1 (3.0.9, 2.2.15 etc.), then you should#       add 'privex.adminplus.backports' BEFORE the 'privex.adminplus' and PVXAdmin apps.#       The backports app is auto-loaded if it's not in INSTALLED_APPS and adminplus detects you need it, but the#       auto-loading will slow down your app's startup, and may cause issues with apps that should only be loaded ONCE.# 'privex.adminplus.backports','privex.adminplus','privex.adminplus.apps.PVXAdmin',# ...'django.contrib.auth','django.contrib.contenttypes',# ...]Register the custom admin in your masterurls.pyfileIn your project's main Django application (generally the folder containingsettings.pyandwsgi.py), you'll
need to comment out any previousadmin.sitestatements, and addsetup_admin(admin)before you define any urls.fromdjango.contribimportadminfromdjango.urlsimportpathfromprivex.adminplus.adminimportsetup_admin# Register Privex AdminPlus to replace the default Django admin system# This will automatically run admin.autodiscover(), so you don't need to call both setup_admin() and admin.autodiscover()setup_admin(admin)# If admin.autodiscover() shouldn't be ran yet, pass discover=False to disable running autodiscover# setup_admin(admin, discover=False)##### Ensure any previous admin.xxx statements are deleted / commented out to avoid conflict.# admin.site = something# admin.sites.site = admin.site# admin.autodiscover()urlpatterns=[# Mount admin.site.urls as normal, no changes needed herepath('admin/',admin.site.urls),# your app URLs...]Notice about AdminPlus Django Back-ports!Why do you include thebackportsmodule, containing code ripped from the official Django project?While Django is well known for their effort towards ensuring backwards compatibility, the Django admin panel is quite
complex, and frequently has potentially breaking updates such as new template files, layout changes, along with use of
newer Django functions such as new template tags.These types of changes can cause Django Admin plugins/wrappers/replacements such as Privex AdminPlus to either stop working,
or may simply cause bugs such as the custom pages admin panel list not rendering correctly, custom views won't load etc.Often, to deal these regressions caused by new Django releases, we have to update Privex AdminPlus to work with the newer
Django version. However, by updating the code to support a newer Django version, it may break AdminPlus on older versions
of Django.To allow Privex AdminPlus to support newer versions of Django, while retaining support for older versions, we include an
additional Django application:privex.adminplus.backportsWhat is thebackportsmodule?Thebackportsapplication is a Django app which contains backported views, admin panel templates, template tags, and
other parts of theofficial Django admin panel codewhich have been copied from a newer version of Django such as3.1,3.2or even from the latest development code.The backported code is lightly tested using the includedexampleappproject, by running the project using a development
server, and then browsing through the admin panel - hand testing both Privex AdminPlus custom views, as well as the
standardModelAdminviews (e.g. creating, editing, viewing and deleting database objects).Note that thebackportsapp is only tested against "older" versions of Django, which are missing at least one critical feature
from the latest stable version of Django that had to be backported.Should I add the backports app to INSTALLED_APPS? / How can I disable backports?Automatic loading of the backports appAs of Privex AdminPlus 1.0.0 - the oldest Django framework version whichdoes not require backportsto be able
to use AdminPlus is Django3.1.0To keep the installation process simple, and to ensure compatibility with those upgrading fromprivex-adminplus < 1.0.0,
theprivex.adminplus.apps.PVXAdminclass contains a Django version check within it'sready()method.If it detects that you're running a Django version which requires backported features, andprivex.adminplus.backportsisn't in yourINSTALLED_APPS, then it will dynamically injectprivex.adminplus.backportsintoINSTALLED_APPS,
and attempt to trigger a re-initialisation of allINSTALLED_APPSto ensure backports gets loaded.If your Django app is configured to log messages which areWARNINGor higher, you may see the automatic backport app loader
in your logs when you first start your app:PrivexAdminPlusConfig.ready :: Django version is < 3.1 :: Ver is: 2.2.15
'privex.adminplus.backports' not in INSTALLED_APPS... adding to apps and re-initialising!
Re-initialising all Django Apps...
Finished re-initialising.Do not rely on the backports auto-loaderWhile the backports app is auto-loaded if it's not in INSTALLED_APPS and adminplus detects you need it,auto-loading will slow down your app's startup, and may cause issues with apps that should only be loaded ONCE.To prevent the risk of strange issues related to the backports auto-loader, if you are running a version of Django older
than 3.1.0 (3.0.9, 2.2.15 etc.), then you should add'privex.adminplus.backports'BEFORE the'privex.adminplus'and PVXAdmin apps in yourINSTALLED_APPSINSTALLED_APPS=['privex.adminplus.backports','privex.adminplus','privex.adminplus.apps.PVXAdmin',# ...]Force disabling the backports auto-loaderIf you are running on an older version of Django which normally requires ourprivex.adminplus.backportsDjango app,
but you don't want to / can't use our backports app, it's possible to disable the backports auto-loader.Reason Examples:Because of another Django app / Python package which conflicts with our backportsBecause you've made your own backports/modifications to views/templates/classes etc. which conflicts with our backports app.NOTE:The backports auto-loader only loadsbackportsif it'snot already loaded(listed in INSTALLED_APPS),
ANDyou're running an older version of Djangowhich requires ourbackportsapp to make pvx-adminplus work at all.To force disable automatic loading ofprivex.adminplus.backports, setAUTO_BACKPORTtoFalsein yoursettings.pyfile for your project.# Disable privex.adminplus's automatic loading of privex.adminplus.backportsAUTO_BACKPORT=FalseINSTALLED_APPS=['privex.adminplus','privex.adminplus.apps.PVXAdmin',# ...]Replace the default admin with Privex AdminPlusFirst you need to comment outdjango.contrib.adminat the start of yourINSTALLED_APPS.Below the commented outdjango.contrib.admin, you'll need to addprivex.adminplusto register the base Django app itself,
followed byprivex.adminplus.apps.PVXAdminto register the admin panel.INSTALLED_APPS=[# 'django.contrib.admin',# NOTE: If you are running a version of Django older than 3.1 (3.0.9, 2.2.15 etc.), then you should#       add 'privex.adminplus.backports' BEFORE the 'privex.adminplus' and PVXAdmin apps.#       The backports app is auto-loaded if it's not in INSTALLED_APPS and adminplus detects you need it, but the#       auto-loading will slow down your app's startup, and may cause issues with apps that should only be loaded ONCE.# 'privex.adminplus.backports','privex.adminplus','privex.adminplus.apps.PVXAdmin',# ...'django.contrib.auth','django.contrib.contenttypes',# ...]Remove any old admin.site statements from yoururls.pyfileIn your project's main Django application (generally the folder containingsettings.pyandwsgi.py), you'll
need to comment out any previousadmin.sitestatements, oradmin.autodiscovery()if they're present.You do NOT need to remove the admin URL mountpath('admin/', admin.site.urls)fromdjango.contribimportadminfromdjango.urlsimportpath###### Ensure any previous admin.xxx statements are comment out to avoid conflict.###### admin.site = something# admin.sites.site = admin.site# admin.autodiscover()urlpatterns=[# Mount admin.site.urls as normal, no changes needed herepath('admin/',admin.site.urls),# your app URLs...]UsageRegistering standard ModelView'sRegister your ModelViews as normal in youradmin.pyfromdjango.contribimportadminfrommyapp.modelsimportSomeModel@admin.register(SomeModel)classSomeModelAdmin(admin.ModelAdmin):passRegistering custom admin viewsYou can register custom views using theprivex.adminplus.admin.register_url, including both function-based and class-based
views. You don't even need to specify a name or URL, it can be automatically inferred from the class/function name.fromprivex.adminplus.adminimportregister_urlfromdjango.httpimportHttpResponsefromdjango.viewsimportView# This would result in the url '{admin_prefix}/hello/' and the human name 'Testing Admin'@register_url(url='hello/')deftesting_admin(request):returnHttpResponse(b"hello world")# This would result in the url '{admin_prefix}/another_test' and the human name 'Another Test'@register_url()defanother_test(request):returnHttpResponse(b"another test view")# This would result in the url '{admin_prefix}/class_view_test' and the human name 'Class View Test'@register_url()classClassViewTest(View):defget(self,*args,**kwargs):returnHttpResponse(b"this is a class view")# You can also hide views from the auto-generated custom admin views list, and you can override their "human friendly name"# which is shown on the custom admin views list on the admin index page::# This would result in the url '{admin_prefix}/lorem' and the human name 'Lorem Ipsum Dolor Generator'@register_url(human="Lorem Ipsum Dolor Generator")deflorem(request):returnHttpResponse(b"lorem ipsum dolor")# This would result in the url '{admin_prefix}/some_internal_view' - and the human name doesn't matter,# as it's hidden - thus does not show up in the custom admin views list@register_url(hidden=True)defsome_internal_view(request):returnHttpResponse(b"this is an internal view, not for just browsing!")Admin views with multiple URLs and route parametersBelow are two examples: multiple URLs for one view by specifying them as a list - and multiple URLs by specifying them
as a dictionary (dicts allow you to set a staticadmin:prefixed name for each URL)fromdjango.contrib.auth.modelsimportUserfromdjango.httpimportHttpResponse,JsonResponse,HttpRequestfromprivex.adminplus.adminimportregister_url# You can specify multiple URLs as a list.# By default, all URLs other than the first one specified will be set as hidden=False - to avoid duplicate# custom view entries in the admin panel@register_url(['user_info/','user_info/<str:username>'])defuser_info(request,username=None):ifusername:u=User.objects.filter(username=username).first()returnJsonResponse(dict(id=u.id,username=u.username,first_name=u.first_name,last_name=u.last_name))returnJsonResponse(dict(error=True,message="no username in URL"))# If you want the URLs to have stable URL names, you can pass the URLs as a dictionary of `url: name` instead,# which will register the URLs under the given names.# NOTE: Just like when passing a list, only the first item in the dictionary will have hidden=False@register_url({'user_info/':'user_info_index','user_info/<str:username>':'user_info_by_username'})defuser_info(request,username=None):ifusername:u=User.objects.filter(username=username).first()returnJsonResponse(dict(id=u.id,username=u.username,first_name=u.first_name,last_name=u.last_name))returnJsonResponse(dict(error=True,message="no username in URL"))When more than one URL is specified inurlusing a list/dict, if hide_extra is True, then only the first URL
in the list/dict of URLs will use the user-specifiedhiddenparameter.
The rest of the URLs will havehidden=TrueTo disable automatically hiding "extra" URLs, pass hide_extra=False like so:@register_url(hide_extra=False)If hide_params is True, URLs which contain route parameters (e.g.<str:username>) will be hidden by default, to prevent
errors caused by trying to reverse their URL in the admin panel custom view list.To disable automatically hiding URLs which contain route parameters, pass hide_params=False like so:@register_url(hide_params=False)Included Example AppFor development and testing purposes, the folderexampleappcontains a basic Django project which tries to use
most features ofprivex-adminplus, so that they can be tested by hand in an actual Django application.To use exampleapp:gitclonehttps://github.com/Privex/adminpluscdadminplus# install requirementspip3install-rrequirements.txt# For exampleapp to be able to resolve the 'privex/adminplus' module, you must set the PYTHONPATH# to the base folder of the privex-adminplus project.exportPYTHONPATH="$PWD"# Enter exampleapp and migrate the Django DB (auto-creates an sqlite3 database at exampleapp/db.sqlite3)cdexampleapp
./manage.pymigrate# Create an admin user./manage.pycreatesuperuser# Start the dev server and then navigate to http://127.0.0.1:8000/admin./manage.pyrunserver