-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from imagescape/feature/django_version_viewer
Init commit for Django Version Veiwer
- Loading branch information
Showing
20 changed files
with
595 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
env/ | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*,cover | ||
.hypothesis/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# pyenv | ||
.python-version | ||
|
||
# celery beat schedule file | ||
celerybeat-schedule | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# dotenv | ||
.env | ||
|
||
# virtualenv | ||
.venv | ||
venv/ | ||
ENV/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
*.sqlite3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,43 @@ | ||
# Pip-Version-Viewer | ||
# Django Version Viewer | ||
|
||
The pip package version viewer plugin allows a queryable endpoint to display a list of dicts representing all installed pip packages in the environment that django is running in. It also allows the insertion of a template tag to any template to display a link which calls up a pop up modal displaying all installed pip packages. You may also configure which users have access to the link and endpoint. | ||
|
||
--------------------------------------- | ||
## Installation | ||
--------------------------------------- | ||
|
||
Add the following to `INSTALLED_APPS` in `settings.py` | ||
|
||
INSTALLED_APPS = [ | ||
'django_version_viewer' | ||
] | ||
|
||
Add `django_version_viewer` include to `urls.py` | ||
|
||
urlpatterns = [ | ||
... | ||
url(r'^django_version_viewer/', include('django_version_viewer.urls')), | ||
... | ||
] | ||
|
||
You can set your own access permissions on the template tag and route by defining your own | ||
`Accessor` class. This class must have a `allow_access` method that returns a `boolean`. By defualt, | ||
django_version_viewer only allows superusers access to the route and template tag. | ||
|
||
# Django Version Viewer settings: | ||
# default class only allows superusers access | ||
ACCESSOR_CLASS_PATH = 'mypathto.my.AccessorClass' | ||
|
||
|
||
Override the `base.html` django Admin template (or the template of your choosing) by creating a `base.html` file inside a `templates/admin` directory in your project. | ||
|
||
Make sure you insert the necessary `src` and `link` blocks so that the popup modal works properly. | ||
|
||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> | ||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> | ||
|
||
Finally, load the template tags file and insert the template tag where ever you want the "Installed Versions" link to show up: | ||
|
||
{% load pip_version_viewer_tags %} | ||
{% show_pip_package_versions %} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
|
||
class Accessor(object): | ||
|
||
def allow_access(self, request): | ||
return request.user.is_superuser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import pip | ||
from operator import itemgetter | ||
|
||
|
||
def list_package_versions(): | ||
installed_packages = pip.get_installed_distributions() | ||
results = [{"package_name": i.key, "package_version": i.version} for i in installed_packages] | ||
return sorted(results, key=itemgetter('package_name')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
{% block content %} | ||
<div> | ||
{% if allow %} | ||
<a id="django_version_viewer" data-toggle="modal" href="#packageModal">Installed Versions</a> | ||
{% endif %} | ||
</div> | ||
|
||
|
||
<!-- Modal --> | ||
<div id="packageModal" class="modal fade" role="dialog"> | ||
<div class="modal-dialog"> | ||
|
||
<!-- Modal content--> | ||
<div class="modal-content"> | ||
<div class="modal-header"> | ||
<button type="button" class="close" data-dismiss="modal">×</button> | ||
<h4 class="modal-title">Versions</h4> | ||
</div> | ||
<div class="modal-body"> | ||
<div class="box" id="packages_box"> | ||
<table> | ||
</table> | ||
</div> | ||
</div> | ||
<div class="modal-footer"> | ||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> | ||
</div> | ||
</div> | ||
|
||
</div> | ||
</div> | ||
{% endblock %} | ||
|
||
|
||
{% block javascript %} | ||
<script> | ||
$( "#django_version_viewer" ).click(function() { | ||
var packages; | ||
$.ajax({ | ||
type: "GET", | ||
url: {% url "django_version_viewer" %}, | ||
csrfmiddlewaretoken: '{{ csrf_token }}', | ||
success: function(data){ | ||
packages = data; | ||
var html = "<tr><th>Package Name</th><th>Package Version</th></tr>"; | ||
$.each(packages, function(i, val) { | ||
html += "<tr><td>"+val.package_name+"</td>"+"<td>"+val.package_version+"</td></tr>" | ||
}); | ||
$('#packages_box>table').html(html); | ||
}, | ||
error: function(){ | ||
} | ||
}); | ||
}); | ||
</script> | ||
{% endblock %} |
Empty file.
18 changes: 18 additions & 0 deletions
18
django_version_viewer/templatetags/pip_version_viewer_tags.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
from pydoc import locate | ||
|
||
from django.conf import settings | ||
from django import template | ||
|
||
|
||
register = template.Library() | ||
accessor_class = locate( | ||
getattr(settings, 'ACCESSOR_CLASS_PATH', 'django_version_viewer.mixins.Accessor')) | ||
accessor = accessor_class() | ||
|
||
|
||
@register.inclusion_tag('version_viewer.html', takes_context=True) | ||
def show_pip_package_versions(context): | ||
if accessor.allow_access(request=context['request']): | ||
return {'allow': True} | ||
else: | ||
return {'allow': False} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
try: | ||
# django 1.6+ | ||
from django.conf.urls import url | ||
except ImportError: | ||
# django <1.6 | ||
from django.conf.urls.defaults import url | ||
|
||
from . import views | ||
|
||
urlpatterns = [ | ||
url(r'^$', views.DjangoVersionViewer.as_view(), name='django_version_viewer'), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from pydoc import locate | ||
|
||
from django.http import HttpResponse | ||
from django.conf import settings | ||
from django.core.exceptions import PermissionDenied | ||
from pip_viewer import list_package_versions | ||
from django.views.generic import View | ||
import json | ||
|
||
accessor_class = locate( | ||
getattr(settings, 'ACCESSOR_CLASS_PATH', 'django_version_viewer.mixins.Accessor')) | ||
accessor = accessor_class() | ||
|
||
|
||
class DjangoVersionViewer(View): | ||
|
||
def get(self, request, *args, **kwargs): | ||
if not accessor.allow_access(request): | ||
raise PermissionDenied | ||
packages = list_package_versions() | ||
return HttpResponse(json.dumps(packages), status=200, content_type="application/json") |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
""" | ||
Django settings for example18 project. | ||
Generated by 'django-admin startproject' using Django 1.8.18. | ||
For more information on this file, see | ||
https://docs.djangoproject.com/en/1.8/topics/settings/ | ||
For the full list of settings and their values, see | ||
https://docs.djangoproject.com/en/1.8/ref/settings/ | ||
""" | ||
|
||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) | ||
import os | ||
|
||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
PROJECT_DIR = os.path.join(BASE_DIR, "example") | ||
|
||
|
||
# Quick-start development settings - unsuitable for production | ||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ | ||
|
||
# SECURITY WARNING: keep the secret key used in production secret! | ||
SECRET_KEY = '*2$rhmg25-#et_b5nt)_oq*u5ymb!xo0*2xl#5(-!h#)m@&bqq' | ||
|
||
# SECURITY WARNING: don't run with debug turned on in production! | ||
DEBUG = True | ||
|
||
ALLOWED_HOSTS = [] | ||
|
||
|
||
# Application definition | ||
|
||
INSTALLED_APPS = ( | ||
'django.contrib.admin', | ||
'django.contrib.auth', | ||
'django.contrib.contenttypes', | ||
'django.contrib.sessions', | ||
'django.contrib.messages', | ||
'django.contrib.staticfiles', | ||
|
||
'django_version_viewer' | ||
) | ||
|
||
MIDDLEWARE_CLASSES = ( | ||
'django.contrib.sessions.middleware.SessionMiddleware', | ||
'django.middleware.common.CommonMiddleware', | ||
'django.middleware.csrf.CsrfViewMiddleware', | ||
'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', | ||
'django.contrib.messages.middleware.MessageMiddleware', | ||
'django.middleware.clickjacking.XFrameOptionsMiddleware', | ||
'django.middleware.security.SecurityMiddleware', | ||
) | ||
|
||
ROOT_URLCONF = 'example18.urls' | ||
TEMPLATES = [ | ||
{ | ||
'BACKEND': 'django.template.backends.django.DjangoTemplates', | ||
'DIRS': [os.path.join(BASE_DIR, 'templates'), ], | ||
'APP_DIRS': True, | ||
'OPTIONS': { | ||
'context_processors': [ | ||
'django.template.context_processors.debug', | ||
'django.template.context_processors.request', | ||
'django.contrib.auth.context_processors.auth', | ||
'django.contrib.messages.context_processors.messages', | ||
], | ||
}, | ||
}, | ||
] | ||
|
||
WSGI_APPLICATION = 'example18.wsgi.application' | ||
|
||
|
||
# Database | ||
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases | ||
|
||
DATABASES = { | ||
'default': { | ||
'ENGINE': 'django.db.backends.sqlite3', | ||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), | ||
} | ||
} | ||
|
||
|
||
# Internationalization | ||
# https://docs.djangoproject.com/en/1.8/topics/i18n/ | ||
|
||
LANGUAGE_CODE = 'en-us' | ||
|
||
TIME_ZONE = 'UTC' | ||
|
||
USE_I18N = True | ||
|
||
USE_L10N = True | ||
|
||
USE_TZ = True | ||
|
||
|
||
# Static files (CSS, JavaScript, Images) | ||
# https://docs.djangoproject.com/en/1.8/howto/static-files/ | ||
|
||
STATIC_URL = '/static/' | ||
|
||
ACCESSOR_CLASS_PATH = 'django_version_viewer.mixins.Accessor' |
Oops, something went wrong.