[[python_wiki:django_configuration]]

Django Configuration

General Information

Configuring the Django Web Framework and its dependencies.


The EXAMPLE sections of code end up building an inventory website.


Checklist


Database: MariaDB

Configuring the MariaDB Database.

  • Configure MariaDB to listen only on localhost
    vim /etc/my.cnf
     
    [mysqld]
    bind-address=127.0.0.1
  • Start/Enable the database
    systemctl enable mariadb
    systemctl start mariadb
  • Run secure setup
    mysql_secure_installation
    • Prompts for the following:
      • Current password for root (should be none, just press enter)
      • Set database root password
      • Remove anonymous users
      • Disallow root logins remotely
      • Remove test databases
      • Reload privilege tables
  • Connect to the database
    mysql -u root -p
  • Create your project's database
    create database myprojecthere character set utf8;
  • Create a database user that Django will use
    create user appuserhere@localhost identified by 'PASSWORDHERE';
  • Grant permissions for the app user on your project's database
    grant all privileges on myprojecthere.* to appuserhere@localhost;
  • Flush privileges
    flush privileges;

Django

Configuring Django.

  • Verify django works
    python
    >>> import django
    >>> print(django.get_version())
    >>> exit()
  • Create a directory to store the project
    mkdir /home/django
    cd /home/django
  • Create a new Django project
    django-admin startproject myprojecthere
    cd /home/django/myprojecthere
  • Create a new Django application inside of the project
    python manage.py startapp myapphere
  • Edit project settings (/home/django/myprojecthere/myprojecthere/settings.py)
    # Allowed Referrer Hosts (hostname and any cnames)
    ALLOWED_HOSTS = ['djangoserver.mycorps.domain.org','myapp.mycorps.domain.org']
     
    # Application definition (add the application, the rest are built in)
    INSTALLED_APPS = [
         # APPNAME.apps.APPCLASSNAME -> see ../myapphere/apps.py
        'myapphere.apps.MyapphereConfig',    # add your application here
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
     
    # Static files (CSS, JavaScript, Images)
    #https://docs.djangoproject.com/en/1.11/howto/static-files/
    STATIC_URL = '/static/'
    STATIC_ROOT = '/var/www/static/'
  • Edit project settings (/home/django/myprojecthere/myprojecthere/settings.py)
    # Database Configuration
    # https://docs.djangoproject.com/en/1.11/ref/settings/#databases
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'myprojecthere',
            'USER': 'appuserhere',
            'PASSWORD': 'PASSWORDHERE',
            'HOST': '127.0.0.1',
            'PORT': '3306',
            'OPTIONS': {
                  'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
            },
        }
    }
  • Run the initial migrate command to create database tables for built in apps that come with Django
    cd /home/django/myprojecthere
    python manage.py migrate
  • Describe your data models (objects that will be stored in the database) (/home/django/myprojecthere/myapphere/models.py) EXAMPLE
    # -*- coding: utf-8 -*-                                                                                                                                            
    from __future__ import unicode_literals
    from django.db import models
     
    # Asset Inventory Example
    class AssetEntry(models.Model):
     
      ##-- Tuples for Use in Field Choices --##
     
      #asset_type choices
      DEVICE_TYPES = ( 
        ('Firewalls', 'Firewalls'), 
        ('Routers', 'Routers'), 
        ('Servers', 'Servers'), 
        ('Storage', 'Storage'), 
        ('Switches', 'Switches'), 
        ('Workstations', 'Workstations'),
      )
     
      # asset_env choices 
      ENV_NAMES = ( 
        ('Dev', 'Development'), 
        ('Test', 'Testing'), 
        ('Prod', 'Production'),
      )
     
      # Linux OS List
      OS_NAMES_LINUX = ( 
        ('CentOS 6', 'CentOS 6'), 
        ('CentOS 7', 'CentOS 7'), 
        ('RHEL 6', 'Red Hat Enterprise Linux 6'), 
        ('RHEL 7', 'Red Hat Enterprise Linux 7'), 
        ('Ubuntu 16.04', 'Ubuntu 16.04'), 
        ('Ubuntu 18.04', 'Ubuntu 18.04'), 
      )
     
      # Windows OS List
      OS_NAMES_WINDOWS = ( 
        ('Win 2008', 'Windows 2008'), 
        ('Win 2012', 'Windows 2012'), 
        ('Win 2016', 'Windows 2016'), 
        ('Win 7', 'Windows 7'), 
        ('Win 10', 'Windows 10'),
      )
     
      # Other OS List
      OS_NAMES_OTHER = ( 
        ('Cisco IOS', 'Cisco IOS'), 
        ('Extreme XOS', 'Extreme XOS'), 
        ('Juniper JunOS', 'Juniper JunOS'), 
        ('NA', 'None'), 
        ('Other', 'Other'), 
        ('VMware ESXi', 'VMware ESXi'), 
      )
     
      # Combined OS List - for asset_os choices
      OS_NAMES = OS_NAMES_LINUX + OS_NAMES_WINDOWS + OS_NAMES_OTHER
     
      # asset_hardware choices 
      HW_TYPES = (
        ('Virtual', 'Virtual'), 
        ('Physical', 'Physical'),
      )
     
      ##-- AssetEntry Fields --##
      asset_name = models.CharField('Name', max_length=50)
     
      asset_type = models.CharField('Device Type', max_length=15, choices=DEVICE_TYPES)
     
      asset_description = models.CharField('Description', max_length=100)
     
      asset_env = models.CharField('Environment', max_length=15, choices=ENV_NAMES)
     
      asset_os = models.CharField('OS Name/Version', max_length = 20, choices=OS_NAMES)
     
      asset_hardware = models.CharField('Hardware: Virtual or Physical', max_length = 15, choices=HW_TYPES)
     
      # Object representation
      def __str__(self):
        return self.asset_name
  • Stage changes to the database
    cd /home/django/myprojecthere
    python manage.py makemigrations myapphere
  • Make changes to the database
    cd /home/django/myprojecthere
    python manage.py migrate
  • Edit project settings (/home/django/myprojecthere/myprojecthere/settings.py)
    # Logging Configuration
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'verbose': {
                'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
                'datefmt' : "%d/%b/%Y %H:%M:%S",
            },
            'simple': {
                'format': '%(levelname)s %(message)s',
            },
        },
        'handlers': {
            'file': {
                'level': 'INFO',
                'class': 'logging.handlers.RotatingFileHandler',
                'filename': '/var/log/myprojecthere/myapphere.log',
                'maxBytes': 500000000, # 500 MB
                'backupCount': 10,
                'formatter': 'verbose',
            },
        },
        'loggers': {
            'django': {
                'handlers': ['file'],
                'level': 'INFO',
                'propagate': True,
            },
            'myapphere': {
                'handlers': ['file'],
                'level': 'INFO',
            },
        },
    }
    ####---- End of Logging Config ----####
  • Create logging directory and setup ownership/permissions
    mkdir /var/log/myprojecthere
    chown :apache /var/log/myprojecthere
    chmod g+rwxs /var/log/myprojecthere
  • Create an admin user
    python manage.py createsuperuser
  • Make your models/objects available for editing in the admin portal (/home/django/myprojecthere/myapphere/admin.py)
    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
     
    from django.contrib import admin
     
    # Register your models here.
     
    # Make Class Available in Admin Portal (see /home/django/myprojecthere/myapphere/models.py)
    from .models import AssetEntry
    admin.site.register(AssetEntry)

A URL+View will generate a web page.

Project Level URLs File

  • Edit project URLs (/home/django/myprojecthere/myprojecthere/urls.py)
     # add the "import include" part or you won't be able to refer to app level url files
    from django.conf.urls import url, include
    from django.contrib import admin
     
    # URL Regex Patterns - Map URIs to App's url file for additional matching
    urlpatterns = [
        # No URI following site name (default app to use)
        url(r'^$', include('myapphere.urls')),
        # URI for app's name
        url(r'^myapphere/', include('myapphere.urls')),
        # Included /admin URI
        url(r'^admin/', admin.site.urls),
    ]


App Level URLs File

  • Create a new App level URLs file (/home/django/myprojecthere/myapphere/urls.py) EXAMPLE
    # urls.py - App URLs Map to App Views
    from django.conf.urls import url
     
    from . import views
     
    urlpatterns = [
      # "/myapphere/" beginning is implied because we are in the "myapphere" urls file already
     
      # /myapphere/  -  All Devices, All Environments (the index)
      url(r'^$', views.index, name='index'),
     
      # /myapphere/stats  -  All Devices, Statistics
      url(r'^stats/$', views.stats, name='stats'),
     
      # /myapphere/env_name  -  All Devices, Specific Environment
      url(r'^(?P<env_name>(dev|test|prod))/$', views.env, name='env'),
     
      # /myapphere/device_type/  - Specific Device, All Environments
      url(r'^(?P<device_type>(firewalls|routers|servers|storage|switches|workstations))/$', views.asset_type_all_env, name='asset_type_all_env'),
     
      # /myapphere/device_type/env_name  -  Specific Device, Specific Environment
      url(r'^(?P<device_type>(firewalls|routers|servers|storage|switches|workstations))/(?P<env_name>(dev|test|prod))/$', views.type_env, name='type_env'),
     
      # /myapphere/<asset_hardware> - Physical or Virtual
      url(r'^(?P<asset_hardware>(physical|virtual))/$', views.asset_hardware, name='asset_hardware'),
    ]
  • Edit the App Views that are loaded depending upon URL match(/home/django/myprojecthere/myapphere/views.py) EXAMPLE
    # views.py - URLs are mapped to views
    # -*- coding: utf-8 -*-                                                                                       
    from __future__ import unicode_literals                                                                              
     
    # Render http response+templates
    from django.shortcuts import render
     
    # Object or 404
    from django.shortcuts import get_object_or_404
     
    # HTTP Response
    from django.http import HttpResponse
     
    # Logging
    import logging
    logger = logging.getLogger(__name__)
     
    # Your Apps Model
    from .models import AssetEntry
     
    # /myapphere/  -  All Devices, All Environments (the index)
    def index(request):
      # Get all asset objects
      all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
     
      # Get number of assets in list
      number_assets = len(all_asset_list)
     
      # Map template variable names (1st) to Python variables (2nd) for use in html templates
      context = { 'all_asset_list': all_asset_list, 'asset_count': number_assets }
     
      # Logging
      logger.info("Rendering index.html - All Devices, All Environments")
     
      # Render the http request, using the template, passing the context
      return render(request, 'myapphere/index.html', context)
     
     
    # /myapphere/stats  -  All Devices, Statistics
    def stats(request):
      # Get all asset objects
      all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
     
      # Get all asset device types
      asset_type_list = [key for key,value in AssetEntry.DEVICE_TYPES]
     
      # Get all os names, Linux only, Windows only
      os_list = [key for key,value in AssetEntry.OS_NAMES]
      os_list_linux = [key for key,value in AssetEntry.OS_NAMES_LINUX]
      os_list_windows = [key for key,value in AssetEntry.OS_NAMES_WINDOWS]
     
      # Log for debug purposes
      #for key in os_list:
      #  logger.info("Field names are: " + key)
     
      #- Build Statistics -#
      # Initialize Stats list (will be a list of dictionaries)
      stats_list = []
     
      ####---- Asset Counts Table: Grand Total Row ----####
      sysstats_grand_total = 0
      sysstats_grand_physical = 0
      sysstats_grand_physical_linux = 0
      sysstats_grand_physical_windows = 0
      sysstats_grand_physical_other = 0
      sysstats_grand_virtual = 0
      sysstats_grand_virtual_linux = 0
      sysstats_grand_virtual_windows = 0
      sysstats_grand_virtual_other = 0
      sysstats_grand_vmware = 0
     
      # Calculate stats for each type of device
      for device_type in asset_type_list:
        # Initialize an empty device stats list
        device_stats = []
     
        # Add node to the device_stats list if a node from the all_asset_list matches the current device type
        for node in all_asset_list:
          if ''.join(node.asset_type.lower().split()) == device_type.lower():
            device_stats.append(node)
     
        ####---- Asset Counts Table ----#### 
        # Total Count
        count_total = len(device_stats)
     
        #- Add to grand total
        sysstats_grand_total += count_total
     
        # Physical and Virtual Counts
        count_physical = 0
        count_physical_linux = 0
        count_physical_windows = 0
        count_physical_other = 0
        count_virtual = 0
        count_virtual_linux = 0
        count_virtual_windows = 0
        count_virtual_other = 0
        for node in device_stats:
          if node.asset_hardware == "Physical":
            count_physical += 1
     
            if node.asset_os in os_list_linux:
              # Physical+Linux Count
              count_physical_linux += 1
            elif node.asset_os in os_list_windows:
              # Physical+Windows Count
              count_physical_windows += 1
            else:
              # Physical+Other OS
              count_physical_other += 1
     
          elif node.asset_hardware == "Virtual":
            # Virtual Count
            count_virtual += 1
     
            if node.asset_os in os_list_linux:
              # Virtual+Linux Count
              count_virtual_linux += 1
            elif node.asset_os in os_list_windows:
              # Virtual+Windows Count
              count_virtual_windows += 1
            else:
              # Virtual+Other OS
              count_virtual_other += 1
     
        #- Add to grand total physical
        sysstats_grand_physical += count_physical
        sysstats_grand_physical_linux += count_physical_linux
        sysstats_grand_physical_windows += count_physical_windows
        sysstats_grand_physical_other += count_physical_other
     
        #- Add to grand total virtual
        sysstats_grand_virtual += count_virtual
        sysstats_grand_virtual_linux += count_virtual_linux
        sysstats_grand_virtual_windows += count_virtual_windows
        sysstats_grand_virtual_other += count_virtual_other
     
        ####---- OS Counts Table ----####
        # Initialize a new empty OS Counts List
        os_counts = []
     
        # Add all the os names and an initial count of 0
        for name in os_list:
          os_counts.append({ 'os_name': name, 'count': 0 })
     
        # Check each node in the devices specific stats
        for node in device_stats:
          # Compare node's OS against each os name in the os_counts list and increment count if a match is found
          for os_entry in os_counts:
            if os_entry['os_name'] == node.asset_os:
              # Increment count value on an os name match
              os_entry['count'] += 1
     
     
        ####---- After All Stats Calculations: Add Device Stats to stats_list ----####
        # Add device statistics to stats_list
        stats_list.append({ 'asset_type': device_type, 'total': count_total, 'physical': count_physical, 'physical_linux': count_physical_linux, 'physical_windows': count_physical_windows, 'physical_other': count_physical_other, 'virtual': count_virtual, 'virtual_linux': count_virtual_linux, 'virtual_windows': count_virtual_windows, 'virtual_other': count_virtual_other, 'os_count_stats': os_counts })
     
        # Grand Total Only: VMware ESXi Host Count
        for node in device_stats:
          if node.asset_os.startswith("VMware"):
            sysstats_grand_vmware += 1
      #-- END OF Calculate Device Type Stats loop --#
     
      ##-- Calculate OS stats grand totals --##
     
      # Initialize a new empty OS Counts Total List
      os_counts_total = []
     
      # Add all the os names and an initial count of 0
      for name in os_list:
        os_counts_total.append({ 'os_name': name, 'count': 0})
     
      # For each device specific stats entry, add up grand total os counts
      for device_entry in stats_list:
        # For each device_entry in the stats_list, go through its os_count_stats value, which is a list of os_names and counts
        for os_device_entry in device_entry['os_count_stats']:
          # Check each os_count_stats os_name against the os_counts_total os_name list
          for os_entry_total in os_counts_total:
            # If we have an os_name match, add the device's os count to the total os count
            if os_entry_total['os_name'] == os_device_entry['os_name']:
              os_entry_total['count'] += os_device_entry['count']
     
      ####---- Add grand totals to stats_list ----####
      stats_list.append({ 'asset_type': 'Total', 'total': sysstats_grand_total, 'physical': sysstats_grand_physical, 'physical_linux': sysstats_grand_physical_linux, 'physical_windows': sysstats_grand_physical_windows, 'physical_other': sysstats_grand_physical_other, 'virtual': sysstats_grand_virtual, 'virtual_linux': sysstats_grand_virtual_linux, 'virtual_windows': sysstats_grand_virtual_windows, 'virtual_other': sysstats_grand_virtual_other, 'os_count_stats': os_counts_total })
     
      #- Other Grand Totals: Calculate -#
      sysstats_grand_linux = sysstats_grand_physical_linux + sysstats_grand_virtual_linux
      sysstats_grand_windows = sysstats_grand_physical_windows + sysstats_grand_virtual_windows
      sysstats_grand_other = sysstats_grand_physical_other + sysstats_grand_virtual_other
     
      # Map template variable names (1st) to the Python variables (2nd) for use in templates
      context = {'device_stats': stats_list, 'total_linux': sysstats_grand_linux, 'total_windows': sysstats_grand_windows, 'total_other': sysstats_grand_other, 'total_vmware': sysstats_grand_vmware, 'os_list': os_list}
     
      # Logging
      logger.info("Rendering stats.html")
     
      # Render the HTTP request, using the template, passing the context
      return render(request, 'myapphere/stats.html', context)
     
     
    # /myapphere/env_name  -  All Devices, Specific Environment
    def env(request, env_name):
      # Get all asset objects
      all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
     
      # New List for the asset types in the passed environment only
      new_list = []
     
      # Check each asset, add to new list if it matches the requested environment name
      for node in all_asset_list:
        if ''.join(node.asset_env.lower().split()) == env_name.lower():
          new_list.append(node)
     
      # Get number of assets in list
      number_assets = len(new_list)
     
      # Map template variable names (1st) to Python variables (2nd) for use in html templates
      context = { 'all_asset_list': new_list, 'env': env_name, 'asset_count': number_assets }
     
      # Logging
      logger.info("Rendering index.html - All Devices, " + env_name)
     
      # Render the http request, using the template, passing the context
      return render(request, 'myapphere/index.html', context)
     
     
    # /myapphere/device/  - Specific Device, All Environments
    def asset_type_all_env(request, device_type):
      # Get all asset objects
      all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
     
      # New List for specific devices only
      new_list = []
     
      # Check each asset, add to new list if it matches the requested device type
      for node in all_asset_list:
        if ''.join(node.asset_type.lower().split()) == device_type.lower():
          new_list.append(node)
     
      # Get number of assets in list
      number_assets = len(new_list)
     
      # Map template variable names (1st) to Python variables (2nd) for use in html templates
      context = { 'all_asset_list': new_list, 'asset_type': device_type, 'asset_count': number_assets }
     
      # Logging
      logger.info("Rendering index.html - Devices: " + device_type + ", All Environments")
     
      # Render the http request, using the template, passing the context
      return render(request, 'myapphere/index.html', context)
     
     
    # /myapphere/device/env_name  -  Specific Device, Specific Environment
    def type_env(request, device_type, env_name):
      # Get all asset objects
      all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
     
      # New List for specific devices and environment only
      new_list = []
     
      # Check each asset, add to new list if it matches the requested device and environment
      for node in all_asset_list:
        if ''.join(node.asset_type.lower().split()) == device_type.lower():
          if ''.join(node.asset_env.lower().split()) == env_name.lower():
            new_list.append(node)
     
      # Get number of assets in list
      number_assets = len(new_list)
     
      # Map template variable names (1st) to Python variables (2nd) for use in html templates
      context = { 'all_asset_list': new_list, 'asset_type': device_type, 'env': env_name, 'asset_count': number_assets }
     
      # Logging
      logger.info("Rendering index.html - Devices: " + device_type + ", Env: " + env_name)
     
      # Render the http request, using the template, passing the context
      return render(request, 'myapphere/index.html', context)
     
     
    # /myapphere/<asset_hardware>/  - Physical or Virtual
    def asset_hardware(request, asset_hardware):
      # Get all asset objects
      all_asset_list = AssetEntry.objects.order_by('asset_type', 'asset_env', 'asset_name')
     
      # New List for asset_hardware (physical or virtual)
      new_list = []
     
      # Check each asset, add to new list if it matches the requested hardware type
      for node in all_asset_list:
        if ''.join(node.asset_hardware.lower().split()) == asset_hardware.lower():
          new_list.append(node)
     
      # Get number of assets in list
      number_assets = len(new_list)
     
      # Map template variable names (1st) to the Python variables (2nd) for use in templates
      context = {'all_asset_list': new_list, 'asset_hardware': asset_hardware, 'asset_count': number_assets }
     
      # Logging
      logger.info("Rendering index.html - All Devices, " + asset_hardware)
     
      # Render the HTTP request, using the template, passing the context
      return render(request, 'myapphere/index.html', context)

Creating the web page templates.

  • Create directory structure
    mkdir -p /home/django/myprojecthere/myapphere/templates/myapphere
  • Create new pages
    • templates/myapphere/index.html
    • templates/myapphere/stats.html

Example page content for the index.html page.

/home/django/myprojecthere/myapphere/templates/myapphere/index.html

<!DOCTYPE html>                                                                            
<html>
<head>
  <title>Asset List</title>
</head>
<body>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'myapphere/style.css' %}" />
 
<!-- Export button jquery (https://github.com/kayalshri/tableExport.jquery.plugin) -->
<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'myapphere/tableExport.js' %}"></script>
<script type="text/javascript" src="{% static 'myapphere/jquery.base64.js' %}"></script>
 
<!-- Layout Divide: Left Side Menu for Devices -->
<table class="layout">
<tr>
<!-- For white gaps in between Device Types and Phys/Virt, this must be larger than stylesheet width -->
<!-- Set to style sheet width+25 px -->
<td class="layout" width="696px">
 
<!-- Device Menu: Determine Active Device -->
<ul class="asset_type">
{% if not asset_type %}
  <li><a class="active" href="/myapphere/">All Devices</a></li>
{% else %}
  <li><a href="/myapphere/">All Devices</a></li>
{% endif %}
 
{% if asset_type == 'firewalls' %}
  <li><a class="active" href="/myapphere/firewalls/">Firewalls</a></li>
{% else %}
  <li><a href="/myapphere/firewalls/">Firewalls</a></li>
{% endif %}
 
{% if asset_type == 'routers' %}
  <li><a class="active" href="/myapphere/routers/">Routers</a></li>
{% else %}
  <li><a href="/myapphere/routers/">Routers</a></li>
{% endif %}
 
{% if asset_type == 'servers' %}
  <li><a class="active" href="/myapphere/servers/">Servers</a></li>
{% else %}
  <li><a href="/myapphere/servers/">Servers</a></li>
{% endif %}
 
{% if asset_type == 'storage' %}
  <li><a class="active" href="/myapphere/storage/">Storage</a></li>
{% else %}
  <li><a href="/myapphere/storage/">Storage</a></li>
{% endif %}
 
{% if asset_type == 'switches' %}
  <li><a class="active" href="/myapphere/switches/">Switches</a></li>
{% else %}
  <li><a href="/myapphere/switches/">Switches</a></li>
{% endif %}
 
{% if asset_type == 'workstations' %}
  <li><a class="active" href="/myapphere/workstations/">Workstations</a></li>
{% else %}
  <li><a href="/myapphere/workstations/">Workstations</a></li>
{% endif %}
 
</ul>
</td>
<!-- END of Layout Divide: Left Side Menu for Devices -->
 
 
<!-- Layout Divide: Right Side Phys and Virt Links -->
<!-- For white gaps in between Phys/Virt and Stats, this must be larger than stylesheet width -->
<!-- Set to style sheet width+25 px -->
<td class="layout" width="188px">
<!-- Asset Type Menu: Physical and Virtual -->
  <ul class ="asset_hardware">
  {% if asset_hardware == 'physical' %}
    <li><a class="active" href="/myapphere/physical/">Physical</a></li>
    <li><a href="/myapphere/virtual/">Virtual</a></li>
  {% elif asset_hardware == 'virtual' %}
    <li><a href="/myapphere/physical/">Physical</a></li>
    <li><a class="active" href="/myapphere/virtual/">Virtual</a></li>
  {% else %}
    <li><a href="/myapphere/physical/">Physical</a></li>
    <li><a href="/myapphere/virtual/">Virtual</a></li>
  {% endif %}
  </ul>
</td>
<!-- END of Layout Divide: Right Side Phys and Virt Links -->
 
 
<!-- Layout Divide: Right Side Additional Links -->
<td class="layout">
<ul class="stats">
  <li><a href="/myapphere/stats/">Stats</a></li>
</ul>
</td>
<!-- END of Layout Divide: Right Side Additional Links -->
 
</tr>
 
 
<!-- Layout Divide: Left Side Environment Menu -->
<tr>
<td class="layout">
 
<!-- Environment Menu: Dynamic Asset Type Links -->
<ul class="env">
{% if env == 'dev' %}
  {% if asset_type %}
    <li><a class="active" href="/myapphere/{{ asset_type }}/dev/">Dev</a></li>
    <li><a href="/myapphere/{{ asset_type }}/test/">Test</a></li>
    <li><a href="/myapphere/{{ asset_type }}/prod/">Prod</a></li>
  {% else %}
    <li><a class="active"href="/myapphere/dev/">Dev</a></li>
    <li><a href="/myapphere/test/">Test</a></li>
    <li><a href="/myapphere/prod/">Prod</a></li>
  {% endif %}
{% elif env == 'test' %}
  {% if asset_type %}
    <li><a href="/myapphere/{{ asset_type }}/dev/">Dev</a></li>
    <li><a class="active" href="/myapphere/{{ asset_type }}/test/">Test</a></li>
    <li><a href="/myapphere/{{ asset_type }}/prod/">Prod</a></li>
  {% else %}
    <li><a href="/myapphere/dev/">Dev</a></li>
    <li><a class="active" href="/myapphere/test/">Test</a></li>
    <li><a href="/myapphere/prod/">Prod</a></li>
  {% endif %}
{% elif env == 'prod' %}
  {% if asset_type %}
    <li><a href="/myapphere/{{ asset_type }}/dev/">Dev</a></li>
    <li><a href="/myapphere/{{ asset_type }}/test/">Test</a></li>
    <li><a class="active" href="/myapphere/{{ asset_type }}/prod/">Prod</a></li>
  {% else %}
    <li><a href="/myapphere/dev/">Dev</a></li>
    <li><a href="/myapphere/test/">Test</a></li>
    <li><a class="active" href="/myapphere/prod/">Prod</a></li>
  {% endif %}
{% else %}
  {% if asset_type %}
    <li><a href="/myapphere/{{ asset_type }}/dev/">Dev</a></li>
    <li><a href="/myapphere/{{ asset_type }}/test/">Test</a></li>
    <li><a href="/myapphere/{{ asset_type }}/prod/">Prod</a></li>
  {% else %}
    <li><a href="/myapphere/dev/">Dev</a></li>
    <li><a href="/myapphere/test/">Test</a></li>
    <li><a href="/myapphere/prod/">Prod</a></li>
  {% endif %}
{% endif %}
</ul>
</td>
<!-- END of Layout Divide: Left Side Environment Menu -->
 
 
<!-- START of Layout Divide: 2nd row for logged in message -->
<td class="layout">
{% if user.is_authenticated %}
  Logged in: {{ user.username }}<br>
  <a class="plain" href="/logout/">Logout</a>
{% endif %}
</td> 
</tr>
<!-- END of Layout Divide: 2nd row for logged in message -->
 
 
<!-- Layout Divide: Bottom Asset List Table -->
<tr>
<td class="layout" colspan=3>
 
<!-- Asset List Above Table: Display Device and Environment -->
<br>
{% if asset_type == 'firewalls' %}
  {% if env == 'dev' %}
  <b>Asset List - Firewalls - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - Firewalls - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - Firewalls - Production Environment</b>
  {% else %}
  <b>Asset List - Firewalls - All Environments</b>
  {% endif %}
 
{% elif asset_type == 'routers' %}
  {% if env == 'dev' %}
  <b>Asset List - Routers - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - Routers - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - Routers - Production Environment</b>
  {% else %}
  <b>Asset List - Routers - All Environments</b>
  {% endif %}
 
{% elif asset_type == 'servers' %}
  {% if env == 'dev' %}
  <b>Asset List - Servers - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - Servers - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - Servers - Production Environment</b>
  {% else %}
  <b>Asset List - Servers - All Environments</b>
  {% endif %}
 
{% elif asset_type == 'storage' %}
  {% if env == 'dev' %}
  <b>Asset List - Storage - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - Storage - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - Storage - Production Environment</b>
  {% else %}
  <b>Asset List - Storage - All Environments</b>
  {% endif %}
 
{% elif asset_type == 'switches' %}
  {% if env == 'dev' %}
  <b>Asset List - Switches - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - Switches - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - Switches - Production Environment</b>
  {% else %}
  <b>Asset List - Switches - All Environments</b>
  {% endif %}
 
{% elif asset_type == 'workstations' %}
  {% if env == 'dev' %}
  <b>Asset List - Workstations - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - Workstations - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - Workstations - Production Environment</b>
  {% else %}
  <b>Asset List - Workstations - All Environments</b>
  {% endif %}
 
{% else %}
  {% if env == 'dev' %}
  <b>Asset List - All Types - Development Environment</b>
  {% elif env == 'test' %}
  <b>Asset List - All Types - Test Environment</b>
  {% elif env == 'prod' %}
  <b>Asset List - All Types - Production Environment</b>
  {% else %}
  <b>Asset List - All Types - All Environments</b>
  {% endif %}
{% endif %}
 
<!-- Physical/Virtual Filter -->
{% if asset_hardware %}
  {% if asset_hardware == 'physical' %}
    <b> - Physical -</b>
  {% elif asset_hardware == 'virtual' %}
    <b> - Virtual -</b>
  {% endif %}
{% endif %}
 
<!-- Assets List Above Table: Number of Assets Displayed -->
{% if asset_count %}
  {% if asset_count == 1 %}
    <b> ({{ asset_count }} asset)</b>
  {% else %}
    <b> ({{ asset_count }} assets)</b>
  {% endif %}
{% else %}
  <b> (0 assets)</b>
{% endif %}
 
<!-- Export Buttons -->
<a href="#" class="plain" onclick="$('#assetlist').tableExport({type:'csv',escape:'false'});"><img src="{% static 'myapphere/csv.png' %}" width="24px" title="Export CSV"></a>
<a href="#" class="plain" onclick="$('#assetlist').tableExport({type:'excel',escape:'false'});"><img src="{% static 'myapphere/xls.png' %}" width="24px" title="Export Excel"></a>
 
<br>
<!-- The Assets List Table -->
<table class="myapphere" id="assetlist">
 <thead>
  <tr class="myapphere">
    <th class="myapphere">Device Type</th>
    <th class="myapphere">Name</th>
    <th class="myapphere">Description</th>
    <th class="myapphere">Environment</th>
    <th class="myapphere">OS</th>
    <th class="myapphere">Hardware</th>
  </tr>
 </thead>
 <tbody
  {% for name in all_asset_list %}
    <tr class="myapphere">
      <td class="myapphere">{{ name.asset_type }}</td>
      <td class="myapphere">{{ name.asset_name }}</td>
      <td class="myapphere">{{ name.asset_description }}</td>
      <td class="myapphere center">{{ name.asset_env }}</td>
      <td class="myapphere center">{{ name.asset_os }}</td>
      <td class="myapphere center">{{ name.asset_hardware }}</td>
    </tr>
  {% endfor %}
 </tbody>
</table>
<!-- END of Assets List Table -->
 
</td>
</tr>
</table>
<!-- END of Layout Divide: Bottom Assets List Table -->
 
<br>
<hr>
<br>
 
</body>
</html>

Example page content for the stats.html page.

/home/django/myprojecthere/myapphere/templates/myapphere/stats.html

<!DOCTYPE html>                                                                            
<html>
<head>
  <title>Asset List - Stats</title>
</head>
<body>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'myapphere/style.css' %}" />
 
<!-- Export button jquery (https://github.com/kayalshri/tableExport.jquery.plugin) -->
<script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
<script type="text/javascript" src="{% static 'myapphere/tableExport.js' %}"></script>
<script type="text/javascript" src="{% static 'myapphere/jquery.base64.js' %}"></script>
 
<!-- Layout Divide: Left Side Menu for Devices -->
<table class="layout">
<tr>
<!-- For white gaps in between Device Types and Phys/Virt, this must be larger than stylesheet width -->
<!-- Set to style sheet width+25 px -->
<td class="layout" width="696px">
 
<!-- Device Menu: No Devices Active on Stats Page -->
<ul class="asset_type">
<li><a href="/myapphere/">All Devices</a></li>
<li><a href="/myapphere/firewalls/">Firewalls</a></li>
<li><a href="/myapphere/routers/">Routers</a></li>
<li><a href="/myapphere/servers/">Servers</a></li>
<li><a href="/myapphere/storage/">Storage</a></li>
<li><a href="/myapphere/switches/">Switches</a></li>
<li><a href="/myapphere/workstations/">Workstations</a></li>
</ul>
</td>
<!-- END of Layout Divide: Left Side Menu for Devices -->
 
 
<!-- Layout Divide: Right Side Phys and Virt Links -->
<!-- For white gaps in between Phys/Virt and Stats, this must be larger than stylesheet width -->
<!-- Set to style sheet width+25 px -->
<td class="layout" width="188px">
<!-- Asset Type Menu: Physical and Virtual -->
  <ul class ="asset_hardware">
  {% if asset_hardware == 'physical' %}
    <li><a class="active" href="/myapphere/physical/">Physical</a></li>
    <li><a href="/myapphere/virtual/">Virtual</a></li>
  {% elif asset_hardware == 'virtual' %}
    <li><a href="/myapphere/physical/">Physical</a></li>
    <li><a class="active" href="/myapphere/virtual/">Virtual</a></li>
  {% else %}
    <li><a href="/myapphere/physical/">Physical</a></li>
    <li><a href="/myapphere/virtual/">Virtual</a></li>
  {% endif %}
  </ul>
</td>
<!-- END of Layout Divide: Right Side Phys and Virt Links -->
 
 
<!-- Layout Divide: Right Side Additional Links -->
<td class="layout">
<ul class="stats">
  <li><a class="active" href="/myapphere/stats/">Stats</a></li>
</ul>
</td>
<!-- END of Layout Divide: Right Side Additional Links -->
 
</tr>
 
 
<!-- START of Layout Divide: 2nd row for logged in message -->
<tr>
<td class="layout">
</td>
 
<td class="layout">
{% if user.is_authenticated %}
  Logged in: {{ user.username }}<br>
  <a class="plain" href="/logout/">Logout</a>                                              
{% endif %}
</td>
</tr>
<!-- END of Layout Divide: 2nd row for logged in message -->
 
 
<!-- Layout Divide: Bottom Stats Table (Asset Counts) -->
<tr>
<td class="layout" colspan=3>
 
<br>
<b>Asset List - Statistics - Asset Counts</b>
 
<!-- Export Buttons -->
<a href="#" class="plain" onclick="$('#assetcounts').tableExport({type:'csv',escape:'false'});"><img src="{% static 'myapphere/csv.png' %}" width="24px" title="Export CSV"></a>
<a href="#" class="plain" onclick="$('#assetcounts').tableExport({type:'excel',escape:'false'});"><img src="{% static 'myapphere/xls.png' %}" width="24px" title="Export Excel"></a>
 
<br>
<!-- Stats Table (Asset Counts) -->
<table class="myapphere" id="assetcounts">
<thead>
  <tr class="myapphere">
    <th class="myapphere">Device Type</th>
    <th class="myapphere">Systems</th>
    <th class="myapphere">Physical</th>
    <th class="myapphere">Physical Linux</th>
    <th class="myapphere">Physical Windows</th>
    <th class="myapphere">Physical Other</th>
    <th class="myapphere">Virtual</th>
    <th class="myapphere">Virtual Linux</th>
    <th class="myapphere">Virtual Windows</th>
    <th class="myapphere">Virtual Other</th>
  </tr>
</thead>
<tbody>
  {% for asset in device_stats %}
    <tr class="myapphere">
      {% if asset.asset_type == 'Total' %}
        <td class="myapphere totals"><b>{{ asset.asset_type }}</b></td>
        <td class="myapphere center totals">{{ asset.total }}</td>
        <td class="myapphere center totals">{{ asset.physical }}</td>
        <td class="myapphere center totals">{{ asset.physical_linux }}</td>
        <td class="myapphere center totals">{{ asset.physical_windows }}</td>
        <td class="myapphere center totals">{{ asset.physical_other }}</td>
        <td class="myapphere center totals">{{ asset.virtual }}</td>
        <td class="myapphere center totals">{{ asset.virtual_linux }}</td>
        <td class="myapphere center totals">{{ asset.virtual_windows }}</td>
        <td class="myapphere center totals">{{ asset.virtual_other }}</td>
      {% else %}
        <td class="myapphere">{{ asset.asset_type }}</td>
        <td class="myapphere center">{{ asset.total }}</td>
        <td class="myapphere center">{{ asset.physical }}</td>
        <td class="myapphere center">{{ asset.physical_linux }}</td>
        <td class="myapphere center">{{ asset.physical_windows }}</td>
        <td class="myapphere center">{{ asset.physical_other }}</td>
        <td class="myapphere center">{{ asset.virtual }}</td>
        <td class="myapphere center">{{ asset.virtual_linux }}</td>
        <td class="myapphere center">{{ asset.virtual_windows }}</td>
        <td class="myapphere center">{{ asset.virtual_other }}</td>
      {% endif %}
    </tr>
  {% endfor %}
  <tr class="myapphere">
    <td class="myapphere totals">Total Linux</td>
    <td class="myapphere center">{{ total_linux }}</td>
  </tr>
  <tr class="myapphere">
    <td class="myapphere totals">Total Windows</td>
    <td class="myapphere center">{{ total_windows }}</td>
  </tr>
  <tr class="myapphere">
    <td class="myapphere totals">Total Other</td>                                          
    <td class="myapphere center">{{ total_other }}</td>
  </tr>
  <tr class="myapphere">
    <td class="myapphere totals">Total VMware ESXi*</td>
    <td class="myapphere center">{{ total_vmware }}</td>
  </tr>
</tbody>
</table>
*Physical Virtual Hosts (VMware ESXi) count is included in Physical Linux/Total Linux counts.
<!-- END of Stats Table (Asset Counts) -->
 
</td>
</tr>
<!-- END of Layout Divide: Bottom Stats Table (Asset Counts) -->
 
<!-- Layout Divide: Bottom Stats Table (OS Counts) -->
<tr>
<td class="layout" colspan=3>
 
<br>
<b>Asset List - Statistics - OS Counts</b>
 
<!-- Export Buttons -->
<a href="#" class="plain" onclick="$('#oscounts').tableExport({type:'csv',escape:'false'});"><img src="{% static 'myapphere/csv.png' %}" width="24px" title="Export CSV"></a>
<a href="#" class="plain" onclick="$('#oscounts').tableExport({type:'excel',escape:'false'});"><img src="{% static 'myapphere/xls.png' %}" width="24px" title="Export Excel"></a>
 
<br>
<!-- Stats Table (OS Counts) -->
<table class="myapphere" id="oscounts">
<thead>
  <tr class="myapphere">
    <th class="myapphere">Device Type</th>
    {% for os_name in os_list %}
      <th class="myapphere">{{ os_name }}</th>
    {% endfor %}
  </tr>
</thead>
<tbody>
  {% for asset in device_stats %}
    <tr class="myapphere">
      {% if asset.asset_type == 'Total' %}
        <td class="myapphere totals"><b>{{ asset.asset_type }}</b></td>
        {% for name in asset.os_count_stats %}
          <td class="myapphere center totals">{{ name.count }}</td>
        {% endfor %}
 
      {% else %}
        <td class="myapphere">{{ asset.asset_type }}</td>
        {% for name in asset.os_count_stats %}
          <td class="myapphere center">{{ name.count }}</td>
        {% endfor %}
      {% endif %}
    </tr>
 
  {% endfor %}
</tbody>
</table>
<!-- END of Stats Table (OS Counts) -->
 
</td>
</tr>
</table>
<!-- END of Layout Divide: Bottom Stats Table (OS Counts) -->
 
<br>
<hr>
<br>
 
</body>
</html>

Configuring stylesheets.

  • Create directory structure
    mkdir -p /home/django/myprojecthere/myapphere/static/myapphere
  • Create stylesheet (/home/django/myprojecthere/myapphere/static/myapphere/style.css)
    /* style.css : Styles for html templates */                                                
     
    /* ---- Table Styles ---- */
    /* table settings */
    table.layout {
      border-collapse: collapse;
      border-spacing: 0px;
      padding: 0px;
    }
    td.layout {
      border-spacing: 0px;
      padding: 0px;
    }
     
    table.myapphere {
      border-collapse: collapse;
    }
     
    /* table headers, table definitions */
    table.myapphere, th.myapphere, td.myapphere {
      border-collapse: collapse;
      border: 1px solid #ddd;
      padding: 5px;
    }
     
    /* th -> table headers */
    th.myapphere {
        background-color: #4CAF50;
        color: white;
    }
     
    /* tr -> table rows
     *  * tr:nth-child -> color every even table row 
     *   * tr:hover -> Mouse hover background color effect */
    tr.myapphere:nth-child(even) {background-color: #f2f2f2;}
    tr.myapphere:hover {background-color: #ddd;}
     
    td.center {
      text-align: center;
    }
     
    td.totals {
      background-color: #b3b3b3;
      font-weight: bold;
    }
     
     
    /* ---- Menu Styles ---- */
    ul.asset_type {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #333;
      width: 671px;
    }
     
    ul.env {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #333;
      width: 163px;
    }
     
    ul.stats {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #333;
      width: 60px;
    }
     
    ul.asset_hardware {
      list-style-type: none;
      margin: 0;
      padding: 0;
      overflow: hidden;
      background-color: #333;
      width: 163px;
    }
     
    li {
      float: left;
    }
     
    li a {
      display: block;
      color: white;
      text-align: center;
      padding: 10px 10px;
      text-decoration: none;
    }
     
    a:hover:not(.active) {
      background-color: #111;
    }
     
    .active {
      background-color:#4CAF50;
    }
     
     
    /* ---- Non-Menu Styles ---- */
    a:link.plain {
      background-color: #ffffff;
    }
    a:visited.plain {
      background-color: #ffffff;
    }
     
    a:hover.plain {
      background-color: #4caf50;
    }

Apache

Configuring Apache to pass traffic to the application.

  • Configure Apache's mod_wsgi for the application (new file)
    vim /etc/httpd/conf.d/myapphere.conf
     
    # Asset List Django/WSGI Config
     
    # WSGIScriptAlias: The base URL to serve the application from
    WSGIScriptAlias / /home/django/myprojecthere/myprojecthere/wsgi.py
     
    # WSGI Daemon Process Config
    WSGIDaemonProcess myapphere python-path=/home/django/myprojecthere
    WSGIProcessGroup myapphere
     
    # Location of Django Application and wsgi.py config
    <Directory /home/django/myprojecthere/myprojecthere>
      <Files wsgi.py>
        Require all granted
      </Files>
    </Directory>
     
    # Static files (admin interface and style sheet)
    Alias /static/ /var/www/static/
    <Directory /var/www/static/>
      Require all granted
    </Directory>
  • Configure the virtual host (new file)
    vim /etc/httpd/conf.d/vhosts.conf
     
    # Virtual Host Config
     
    # Redirect shortname to fully qualified
    <VirtualHost *:80>
      ServerName djangoserver
      Redirect "/" "http://djangoserver.mycorps.domain.org/"
    </VirtualHost>
     
    # Redirect all http to https
    <VirtualHost *:80>
      ServerName djangoserver.mycorps.domain.org
     
      <IfModule mod_rewrite.c>
        # Redirect all to https
        RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
      </IfModule>
    </VirtualHost>
     
     
    # Redirect shortname to fully qualified
    <VirtualHost *:443>
      ServerName djangoserver
      Redirect "/" "https://djangoserver.mycorps.domain.org/"
    </VirtualHost>
     
    # Django Application lives here at the root /. See: /etc/httpd/conf.d/myapphere.conf
    <VirtualHost *:443>
      # Fully qualified server name
      ServerName djangoserver.mycorps.domain.org
      Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
    </VirtualHost>
     
    <VirtualHost *:443>
      # OPTIONAL: CNAME for website - will only work with SSL if using a wildcard certificate
      ServerName myapphere.mycorps.domain.org
      Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
    </VirtualHost>
  • Configure SSL Certificate
    vim /etc/httpd/conf.d/ssl.conf
     
    SSLCertificateFile /etc/pki/tls/certs/current_crt.crt
    SSLCertificateKeyFile /etc/pki/tls/certs/current_key.key
    SSLCertificateChainFile /etc/pki/tls/certs/current_ca.crt
  • Start and Enable Apache
    systemctl start httpd
    systemctl enable httpd

Django: Authentication

Adding authentication to Django requires basic auth to be setup first, as LDAP auth builds upon it.

Basic authentication uses Django local user accounts.

  • Edit Project Settings (/home/django/myprojecthere/myprojecthere/settings.py)
    # Redirect Successful Logins Here
    LOGIN_REDIRECT_URL = '/myapphere/'
     
    # Ensure contrib.auth is added to installed apps:
    # Application definition
    INSTALLED_APPS = [
        'myapphere.apps.MyapphereConfig',
        'django.contrib.admin',
        'django.contrib.auth',    # must exist for basic auth to work
    ...
    ]
  • Add login and logout URLs to project URLs (/home/django/myprojecthere/myprojecthere/urls.py)
    # auth views - authentication login/logout module
    from django.contrib.auth import views as auth_views
     
    # URL Patterns - Map to Projects Within Django
    urlpatterns = [
        ...
        # Login URLs
        url(r'^login/$', auth_views.login, {'template_name': 'login.html'}, name='login'),
        url(r'^logout/$', auth_views.logout, {'next_page': '/login/'}, name='logout'),
        ...
    ]
  • Edit the application views (/home/django/myprojecthere/myapphere/views.py)
    # Require login decorator
    from django.contrib.auth.decorators import login_required
     
    # Put login decorator before every function definition that you want to require login to view:
    #-> Require login for the view following it <-#
    @login_required(login_url="/login/")
     
    def index(request):
  • Create a HTML Login Page (/home/django/myprojecthere/myapphere/templates/login.html)
    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>{% block title %}Asset List{% endblock %}</title>
    </head>
     
    <body>
      <header>
        <h1>Asset List</h1>
        {% if user.is_authenticated %}
          Greetings, {{ user.username }}.
          <a href="{% url 'logout' %}">logout</a>
        {% endif %}
      </header>
     
      <hr>
      <main>
      <h2>Login</h2>
      <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Login</button>
      </form>
      </main>
      <hr>
     
    </body>
    </html>

Configuring LDAP authentication.

  • Install the python django ldap package
    pip install django-auth-ldap
  • Edit Project Settings (/home/django/myprojecthere/myprojecthere/settings.py)
     # LDAP Module Imports
    import ldap
    from django_auth_ldap.config import LDAPSearch
    from django_auth_ldap.config import GroupOfNamesType
    from django_auth_ldap.config import LDAPGroupQuery
     
    # Authentication Backends (LDAP and Django Local)
    AUTHENTICATION_BACKENDS = (
        'django_auth_ldap.backend.LDAPBackend',
        'django.contrib.auth.backends.ModelBackend',
    )
     
    ####- LDAP Server Config -####
    AUTH_LDAP_SERVER_URI = "ldap://LDAPSERVER01.mycorps.domain.org ldap://LDAPSERVER02.mycorps.domain.org"
    AUTH_LDAP_START_TLS = True
     
    # Bind Info: Use authenticating user to get user and group info
    AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = True
    AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,cn=users,cn=accounts,dc=mycorps,dc=domain,dc=org"
     
    # Cache LDAP Groups for use with permissions
    AUTH_LDAP_CACHE_GROUPS = True
    AUTH_LDAP_GROUP_CACHE_TIMEOUT = 3600
     
    # Group Info Gathering
    AUTH_LDAP_GROUP_SEARCH = LDAPSearch
      "cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org",
      ldap.SCOPE_SUBTREE,
      "(objectClass=groupofnames)"
    )
    AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
     
    # Group restrictions - Who can login via LDAP
    AUTH_LDAP_REQUIRE_GROUP = (
     
      # Allow login for members of the LDAP group "list_users"
      LDAPGroupQuery("cn=list_users,cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org") |
     
      # Allow login for members of the LDAP group "admin_group"
      LDAPGroupQuery("cn=admin_group,cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org")
    )
     
    # Use LDAP group membership to calculate group permissions.
    AUTH_LDAP_FIND_GROUP_PERMS = True
     
    # Update Django record from LDAP each time user logs in
    AUTH_LDAP_ALWAYS_UPDATE_USER = True
     
    # Populate the Django user info from LDAP directory info
    AUTH_LDAP_USER_ATTR_MAP = {
        "first_name": "givenname",
        "last_name": "sn",
        "email": "mail"
    }
     
    # Set user permission flags by group - set LDAP group "admin_group" as Django Staff Members
    AUTH_LDAP_USER_FLAGS_BY_GROUP = {
        "is_staff": "cn=admin_group,cn=groups,cn=accounts,dc=mycorps,dc=domain,dc=org"
    }

Django: Jquery

Jquery can be added in order to enable an Export as CSV and/or Excel buttons.

Reference: Export Jquery Buttons: https://github.com/kayalshri/tableExport.jquery.plugin

  • From the reference link, download:
    • jquery.base64.js
    • tableExport.js
  • Search the internet for CSV and XLS icons. Download them.
    • CSV = save as “csv.png”
    • XLS = save as “xls.png”
  • Save the Javascript files and small pictures (CSV/XLS) into the same directory as the style sheet
    /home/django/myprojecthere/myapphere/static/myapphere/
  • Install the Django Jquery integration
    pip install django-jquery
  • Add Jquery to the “INSTALLED_APPS” list (/home/django/myprojecthere/myprojecthere/settings.py)
    # Application definition
    INSTALLED_APPS = [
        'jquery',
  • Add jquery to HTML templates
    <!-- Export button jquery support (https://github.com/kayalshri/tableExport.jquery.plugin) -->
    <script type="text/javascript" src="{% static 'js/jquery.js' %}"></script>
    <script type="text/javascript" src="{% static 'myapphere/tableExport.js' %}"></script>
    <script type="text/javascript" src="{% static 'myapphere/jquery.base64.js' %}"></script>
     
    <!-- Export Buttons -->
    <a href="#" class="plain" onclick="$('#assetlist').tableExport({type:'csv',escape:'false'});"><img src="{% static 'myapphere/csv.png' %}" width="24px" title="Export CSV"></a>
    <a href="#" class="plain" onclick="$('#assetlist').tableExport({type:'excel',escape:'false'});"><img src="{% static 'myapphere/xls.png' %}" width="24px" title="Export Excel"></a>

Django: Static Files

No matter which steps from above you skip, you absolutely need to collect static files to copy them into the location Apache expects them to be.

This is for Apache's access to javascript, css, etc.

  • Collect static files
    cd /home/django/myprojecthere/
    python manage.py collectstatic

DEBUG: TURN OFF

Lastly, when you are not developing/debugging your site, turn off debug mode to avoid dumping sensitive information to the screen in the event of an error.


Edit the project settings (/home/django/myprojecthere/myprojecthere/settings.py)

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

Next Steps

  • python_wiki/django_configuration.txt
  • Last modified: 2019/05/26 03:50
  • (external edit)