In this article, you'll go from creating a Django project to displaying your home, account, and login screens. Most of them are personal notes, but I hope you find them helpful. Operation cannot be guaranteed.
Authentication uses django-allauth. Editing and testing screens with django-allauth is described in Creating a Login Screen with Django allauth.
Create a django project location with the following command.
mkdir ec-django
Create a virtual environment for python and install the required packages.
cd ec-django/
python -m venv venv
//Enter the virtual environment
source venv/bin/activate
//Package installation in virtual environment
pip install Django==2.2
pip install django-allauth==0.39.1 //Authentication functions such as login function
pip install django-environ==0.4.5 //Environment variables.To read from an env file
pip install mysqlclient==1.4.4 //For Mysql database
//pip install stripe==2.35.0 //Payment function by stripe
Create a project.
django-admin startproject config .
Create an application (main) that manages users.
./manage.py startapp main
Create other necessary directories.
//Directory of python files for easy processing
mkdir script
touch ./script/__init__.py
//templates file(.html etc.)Directory to put
mkdir templates
//Directory to put static files
mkdir static
Creating an .env file
touch .env
Environment variables are added to the following .env file each time a function is added. If you publish it on the net such as git, be careful not to upload it.
.env
DEBUG=Ture
SECRET_KEY=<django-secret-key> //./config/setting.py secret key
//The following are the settings related to the database. (Match with the DB set in the latter half of the article.)
DB_NAME=databese-name
DB_USER=user-name
DB_PASS=password
Create a program that reads environment variables. The following program also reads the DB information and the path to the base directory of your Django project, which you'll set later in this article.
import environ
import os
from config.settings.base import BASE_DIR #Set later
import logging
logger = logging.getLogger(__file__)
def get_env_dict(env_path):
env = {}
try:
read_env = environ.Env()
environ.Env.read_env(env_path)
#less than,.Write about the parameters to read from the env file.
if read_env('DEBUG') == 'True' or True:
env['DEBUG'] = True
elif read_env('DEBUG') == 'False' or False:
env['DEBUG'] = False
#secret keys
env['SECRET_KEY'] = read_env('SECRET_KEY')
#DB setting
env['DB_NAME'] = read_env('DB_NAME')
env['DB_USER'] = read_env('DB_USER')
env['DB_PASS'] = read_env('DB_PASS')
except environ.ImproperlyConfigured as e:
logger.info('Key that is not set is set: {}'.format(e))
except Exception as e:
logger.info('Environment variable setting error: {e}'.format(e))
return env
env_path = os.path.join(BASE_DIR, '.env')
env = get_env_dict(env_path)
I referred to the following. Django's DATABASE settings that I always do when using MySQL (utf8mb4) with Django MySQL Setup on Mac
brew install mysql
//mysql --version
//mysql Ver 14.14 Distrib 5.7.25, for osx10.14 (x86_64) using EditLine wrapper
mysql.server start
mysql -u root -p
//DB name database-name,Username user-name,Password password
mysql> CREATE DATABASE database-name;
mysql> CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON database-name.* TO 'user-name'@'localhost';
mysql> FLUSH PRIVILEGES;
//If you run tests in Django
mysql> GRANT ALL PRIVILEGES ON test_django_test.* TO 'mysiteuser'@'localhost';
Create a configuration file. The configuration file is. Although it is ./config/settings.py, create a configuration file for development as follows.
mkdir ./config/settings
touch ./config/settings/__init__.py
touch ./config/settings/base.py
touch ./config/settings/development.py
python:./config/settings/base.py
import os
###############
# Build paths #
###############
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #Fixed by file change
PROJECT_NAME = os.path.basename(BASE_DIR)
############
# Security #
############
DEBUG = False
ALLOWED_HOSTS = []
#################
# Core settings #
#################
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
#django-allauth
'allauth',
'allauth.account',
'allauth.socialaccount',
#main app
'main.apps.MainConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates', 'allauth'), #Place to put login template etc.
os.path.join(BASE_DIR, 'templates'), #Where to put the template
],
'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 = 'config.wsgi.application'
##################
# Authentication #
##################
AUTH_USER_MODEL = "main.User" #main/model.To use the User model to be set in py for authentication
#URL to transition after login process
LOGIN_REDIRECT_URL = 'home'
#URL to transition to after logout processing
ACCOUNT_LOGOUT_REDIRECT_URL = 'home'
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend', #Email settings are made in Custom User, so settings are required
)
#Set the authentication method to an email address
ACCOUNT_AUTHENTICATION_METHOD = 'email'
#Request an email address when creating an account
ACCOUNT_EMAIL_REQUIRED = True
#Do not send user registration confirmation email:When sending'option'
ACCOUTN_EMAIL_VERIFICATION = 'none'
#Do not use USER name (I commented out the following, so in this project, I will request it when creating an account: default)
#ACCOUNT_USERNAME_REQUIRED = False
#With the logout button, you can immediately transition to the redirect destination without transitioning to the logout screen.
ACCOUNT_LOGOUT_ON_GET = True
#all-auth used to determine site
SITE_ID = 1
############
# Database #
############
DATABASES = {}
############
# Messages #
############
MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
###########
# Logging #
###########
LOGGING = {}
#######################
# Password validation #
#######################
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
########################
# Internationalization #
########################
LANGUAGE_CODE = 'ja' #Set for Japan
TIME_ZONE = 'Asia/Tokyo' #Set for Japan
USE_I18N = True
USE_L10N = True
USE_TZ = True
################
# Static files #
################
#Set where to put static files
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
STATIC_ROOT = '/var/www/{}/static'.format(PROJECT_NAME)
#Set the location to put the media files
MEDIA_URL = '/media/'
MEDIA_ROOT = '/var/www/{}/media'.format(PROJECT_NAME)
python:./config/settings/development.py
from .base import *
from script.get_env_dict import env
#####################
# Security settings #
#####################
DEBUG = True
SECRET_KEY = env['SECRET_KEY']
ALLOWED_HOSTS = ['*']
############
# Database #
############
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': env['DB_NAME'], #Created database name
'USER': env['DB_USER'], #Login user name
'PASSWORD': env['DB_PASS'],
'HOST': 'localhost',
'PORT': '3306',
'ATOMIC_REQUESTS': True, #transaction
'OPTIONS': {
'charset': 'utf8mb4',
'sql_mode': 'TRADITIONAL,NO_AUTO_VALUE_ON_ZERO,ONLY_FULL_GROUP_BY',
},
"TEST": {
'NAME' : 'test_django_test'
}
}
}
###########
# Logging #
###########
LOGGING = {
#Version is fixed to "1"
'version': 1,
#Do not invalidate existing log settings
'disable_existing_loggers': False,
#Log format
'formatters': {
#For development
'develop': {
'format': '%(asctime)s [%(levelname)s] %(pathname)s:%(lineno)d ' '%(message)s'
},
},
#handler
'handlers': {
#Handler for console output
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'develop',
},
},
#Logger
'loggers': {
#A logger that picks up logs for all self-made applications
'': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False,
},
#A logger that picks up all the logs that Django itself puts out
'django-test': {
'handlers': ['console'],
'level': 'INFO',
'propagate': False,
},
},
}
################
# Static files #
################
STATIC_ROOT = os.path.join(BASE_DIR, 'static-root')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
##################
# Email settings #
##################
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
Modify ./manage.py so that development.py is selected when DEBUG in the .env file is True.
python:./manage.py
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
from script.get_env_dict import env
def main():
#.Development when DEBUG of env file is True.Load py
if env['DEBUG'] == True:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development')
elif env['DEBUG'] == False:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.development') ## TODO :Settings related to the production environment are described separately.
from django.db.backends.mysql.schema import DatabaseSchemaEditor
DatabaseSchemaEditor.sql_create_table += " ROW_FORMAT=DYNAMIC"
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
Here, set the URL pattern to the project management screen, login screen in django-allauth, and screen related to main / urls.py.
python:./config/urls.py
from django.contrib import admin
from django.urls import path, include
from script.get_env_dict import env
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls), #Project management screen
path('accounts/', include('allauth.urls')), #Account management functions such as login
path('', include('main.urls')), #Things related to the main application such as the home screen
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Set the url of the screen related to the main application.
./main Since urls.py is not included in the app, create urls.py
When registering a User name, a regular expression limit (username_regex) and a minimum number of characters limit (MinLengthValidator) are added as validation functions.
touch ./main/urls.py
Set the path to the home screen.
urls.py
from django.contrib import admin
from django.views.generic import TemplateView
from django.urls import path, include
from main import views
urlpatterns = [
path('', TemplateView.as_view(template_name="main/home.html"), name='home'),
]
As a User model, username and email required for account creation are set. Here, the characters that can be used for username are restricted.
python:./main/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.core.validators import MinLengthValidator, RegexValidator
from django.utils.translation import gettext_lazy as _ #For internationalization such as translation function
class User(AbstractUser):
"""Custom user to perform authentication by email """
username_validator = UnicodeUsernameValidator()
username_regex = RegexValidator(regex=r'^[a-zA-Z0-9][a-zA-Z0-9\-]+', message="Characters that cannot be used in the user name are specified.")
username = models.CharField(_('username'), max_length=150, unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[username_validator, username_regex, MinLengthValidator(5)],
error_messages={
'unique': _("A user with that username already exists."),
},
)
email = models.EmailField('emial address', unique=True)
Since the User model is set in models.py, migration is performed.
//DB startup
mysql.server start
//Creating a migration file
./manage.py makemigrations
//Migrate to DB
./manage.py migrate
If you make a mistake in the model and re-migrate the DB, and if you can delete the DB during development, you can initialize it with the following command.
//Delete migration file
find . -path "*/migrations/0*.py" -delete
find . -path "*/migrations/__pycache__/0*.pyc" -delete
//Delete / reset database
mysql -u root -p
mysql> drop database database-name;
mysql>create database database-name;
mysql>exit;
mysql.server restart
Create main / home.html set in ./main/urls.py.
mkdir ./templates/main
touch ./templates/main/home.html
<!DOCTYPE html>
<html lang="js">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>Hello djanog !!</h1>
</body>
</html>
Start the server with the following command
./manage.py runserver
If you access http: // localhost: 8000 / in your browser, you should see a screen that says Hello djanog !!. Also, if you access http: // localhost: 8000 / accounts / signup /, the account creation screen will be displayed. Also, if you access http: // localhost: 8000 / accounts / login /, the login screen will be displayed.
For example, the following screen will be displayed.
For many parts of this article, I referred to the following textbooks. Perhaps this article alone is not enough to complement, so buy the following books !! It's a really good book.
Recommended Posts