- Initial project creation
- Create the django project
- Add the first content
- My extensions
- Configuration
Initial project creation
Prepare project and venv
$ mkdir <PROJECTNAME> $ cd <PROJECTNAME> $ python -m venv venv $ source venv/bin/activat $ pip install Django
Activate your venv
Every time you want to use your django project, you need to enable the venv. This venv activation will not be mentioned in the rest of the instruction.
$ source venv/bin/activat
Create the django project
Create the project
The basic django environment can be created by the following command:
$ django-admin startproject <PROJECTNAME> .
Create your app
A django project can consist out of multiple apps. With this command you are able to create your own first app:
$ django-admin startapp <APP>
and add the following line to the list INSTALLED_APPS of your <PROJECTNAME>/settings.py:
'<APP>.apps.<APP_as_camelcase>Config',
Migrate
After data structure changes you need to do a migration. After initially creating a project you also need to do a migration by:
python manage.py migrate
Start the server
Now you are able to start the server. You havn't created content yet. Therefore you see a welcome page when you visit http://127.0.0.1:8000 (also mentioned in the output of the command starting the server):
$ python manage.py runserver
Add the first content
Create an example view
In the file <app>/views.py you can create a method, which is called, if a defined page is executed. Here is an example for your view file:
from django.http import HttpResponse from django.conf import settings import logging logger = logging.getLogger(settings.ROOT_LOGGER_NAME).getChild(__name__) def example(request, rel_path=''): logger.info("Someone called the example page. The page was rel_path=%s", rel_path) return HttpResponse("This is an example only...")
Remark: You need to define ROOT_LOGGER_NAME in your settings.py or add the logging configuration (see section below).
Add the example view to your project
You can choose one of the following sections for adding your first page to an url. In both cases, you edit the file <PROJECTNAME>/urls.py.
Add the view directly
Import your <APP> on the top beneath the other imports
import <APP>.views
and add the following line to the list urlpatterns:
path('<APP>/', <APP>.views.example, name='<APP>-example'), path('<APP>/<path:rel_path>', <APP>.views.example, name='<APP>-example'),
Add views by an import
Import include on the top beneath the other imports
from django.urls import include
and add the following line to the list urlpatterns:
path('<APP>/', include('<APP>.urls')),
In addition you need to create the file <APP>/urls.py, where you can define the <APP> urls:
from django.urls import path from . import views urlpatterns = [ path('', views.example, name='app-example'), path('<path:rel_path>', views.example, name='app-example'), ]
Inspect your first page
In the urls.py we defined two urls. The first is the root page (assuming <APP> was app)
The second url definition is for all subpages below this url. Here an example
http://127.0.0.1:8000/app/any/random/subpage
Remark: We added a log entry, but we can't see that log. See the logging section at the configuration.
My extensions
Themes
This extension provides a clear theme. See also here.
Users
This extension provides basic user actions (login, logout, register, ...). See also here.
Mycreole
This extension provides the possibility to use creole markup language for for pages. See also here.
Configuration
Config extention
config.py
This config extention makes it possible to move user specific parameters to a config.py.
Remark: Your config.py shall have a SECRET_KEY definition and the access to that file shall be limited to the owner.
Here is an example of such a config.py:
####################################################################### # Configuration of your django application ####################################################################### # # Django # # This defines the mode of the running server # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True # This a the secret key for your application. # SECURITY WARNING: don't run with a dummy secret in production! And don't let others read this key! #SECRET_KEY = "Insecure_KEY" # This defines the listener hostnames for your django server # SECURITY WARNING: don't run with '0.0.0.0' in in production, unless you know what you are doing! #ALLOWED_HOSTS = ['<YOUR_SERVER_HOSTNAME>', ] # This might be needed for usage in a docker environment #CSRF_TRUSTED_ORIGINS = ['<YOUR_SERVER_URL>', ] # # Themes library # # This defines the default theme, if no theme is set in the django parameters #DEFAULT_THEME= 'clear-blue',
Settings extentions
Place these imports on the top of the file <PROJECTNAME>/settings.py:
import config from logging.handlers import SocketHandler as _SocketHandler import os import random import stat import sys
and add this code at the very end
# Check permission of config.py # if sys.platform == 'linux' or sys.platform == 'linux2': st = os.stat(os.path.join(BASE_DIR, 'config.py')) if st.st_mode & stat.S_IRGRP or st.st_mode & stat.S_IROTH: raise PermissionError("conig.py is readable by group or others.") # Default values, if not defined in config.py # USER_CONFIG_DEFAULTS = { 'DEBUG': False, 'SECRET_KEY': None, 'DEFAULT_THEME': 'clear-blue', 'ALLOWED_HOSTS': ['127.0.0.1', 'localhost', ], 'CSRF_TRUSTED_ORIGINS': [], } # Set configuration parameters # thismodule = sys.modules[__name__] for property_name in USER_CONFIG_DEFAULTS: try: value = getattr(config, property_name) except AttributeError: value = USER_CONFIG_DEFAULTS[property_name] setattr(thismodule, property_name, value) # SECURITY WARNING: keep the secret key used in production secret! # if SECRET_KEY is None: chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)' s_key = ''.join([random.choice(chars) for n in range(50)]) secret_key_warning = "You need to create a config.py file including at least a SECRET_KEY definition (e.g.: --> %s <--). " % repr(s_key) raise KeyError(secret_key_warning)
Logging
To enable the logging of your personal modules, you need to adapt the settings.py. In debug mode the logging will be passed to a socket. You need a tool to view the logs (e.g. cutelog).
# Logging Configuration # ROOT_LOGGER_NAME = os.path.basename(os.path.dirname(__file__)) default_handler = ['socket', 'console'] if DEBUG else ['console'] class DjangoSocketHandler(_SocketHandler): def emit(self, record): if hasattr(record, 'request'): record.request = None return super().emit(record) LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'short': { 'format': "%(name)25s - %(levelname)10s - %(message)s", 'datefmt': '[%d/%b/%Y %H:%M:%S]', }, 'long': { 'format': """~~~~(%(levelname)-10s)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ File "%(pathname)s", line %(lineno)d, in %(funcName)s %(asctime)s: %(name)s - %(message)s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~""", }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'short', }, 'socket': { 'level': 'DEBUG', 'class': f'{ROOT_LOGGER_NAME}.settings.DjangoSocketHandler', 'host': '127.0.0.1', 'port': 19996, }, }, }, 'loggers': { 'django': { 'handlers': ['console'], 'level': 'INFO', 'propagate': False, }, ROOT_LOGGER_NAME: { 'handlers': ['console'], 'level': 'DEBUG' if DEBUG else 'INFO', 'propagate': False, }, }, }