djbase

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 245cc45e5e476a9c1cf9d6c44fedd4e3bc1197a9
Author: srfsh <srfsh@sonu.ch>
Date:   Mon, 28 Jun 2021 13:31:29 +0300

Init

Diffstat:
A.editorconfig | 13+++++++++++++
A.ex/dev.py | 13+++++++++++++
A.ex/prod.py | 12++++++++++++
A.gitignore | 12++++++++++++
ALICENSE | 13+++++++++++++
AMakefile | 23+++++++++++++++++++++++
AREADME.md | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abase/__init__.py | 0
Abase/asgi.py | 7+++++++
Abase/settings/__init__.py | 1+
Abase/settings/common.py | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abase/urls.py | 20++++++++++++++++++++
Abase/wsgi.py | 7+++++++
Amanage.py | 25+++++++++++++++++++++++++
Apage/__init__.py | 0
Apage/admin.py | 3+++
Apage/apps.py | 6++++++
Apage/migrations/__init__.py | 0
Apage/models.py | 1+
Apage/tests.py | 3+++
Apage/urls.py | 12++++++++++++
Apage/views.py | 11+++++++++++
Apoetry.lock | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apyproject.toml | 20++++++++++++++++++++
Astatic/base/css/style.css | 0
Astatic/base/img/icon.ico | 0
Astatic/base/js/script.js | 0
Atempl/base/footer.html | 3+++
Atempl/base/layout.html | 16++++++++++++++++
Atempl/base/navbar.html | 7+++++++
Atempl/page/about.html | 5+++++
Atempl/page/contact.html | 5+++++
Atempl/page/home.html | 6++++++
33 files changed, 550 insertions(+), 0 deletions(-)

diff --git a/.editorconfig b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab +indent_size = tab +tab_width = 8 + +[*.md] +trim_trailing_whitespace = false diff --git a/.ex/dev.py b/.ex/dev.py @@ -0,0 +1,13 @@ +from .common import BASE_DIR + +DEBUG = True +PORT = "8000" +INTERNAL_IPS = ["localhost", "127.0.0.1", "::1"] +SECRET_KEY = "secret_me_harder" +ALLOWED_HOSTS = ["localhost", "127.0.0.1", "::1"] +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + }, +} diff --git a/.ex/prod.py b/.ex/prod.py @@ -0,0 +1,12 @@ +from .common import BASE_DIR + +DEBUG = False +INTERNAL_IPS = ["localhost", "127.0.0.1", "::1"] +SECRET_KEY = "openssl rand -hex 16" +ALLOWED_HOSTS = ["localhost", "127.0.0.1", "::1"] +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + }, +} diff --git a/.gitignore b/.gitignore @@ -0,0 +1,12 @@ +# exclude the custom settings from the project +/base/settings/dev.py +/base/settings/prod.py + +# STATIC_ROOT and MEDIA_ROOT +/asset/ + +/.vscode/ +/db.sqlite3 + +*.pyc +__pycache__/ diff --git a/LICENSE b/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2021 Senior Fish <srfsh@sonu.ch> + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile @@ -0,0 +1,23 @@ +all: start-django + +start-django: + @poetry run ./manage.py runserver + +migrate: + @poetry run ./manage.py migrate + +static: + @poetry run ./manage.py collectstatic + +sh: + @poetry run ./manage.py shell + +dev-deps: + @poetry install + +prod-deps: + @poetry install --no-dev -Ewsgi + +.POSIX: +.SUFFIXES: +.PHONY: all start-django migrate static sh dev-deps prod-deps diff --git a/README.md b/README.md @@ -0,0 +1,81 @@ +# Django Base +A project template to bootstrap common projects. + +## Getting Started +Chose one of the stage you want to bootstrap and run the commands. + +**development** +``` +make dev-deps +cp .ex/dev.py base/settings/ +# edit base/settings/dev.py +make migrate +make +``` + +**production** +``` +make prod-deps +cp .ex/prod.py base/settings/ +# edit base/settings/prod.py +make migrate +make static +# set up a wsgi daemon and a fcgi daemon +``` + + +## Project Structure +Important project files: + +<dl> +<dt>/base/</dt> +<dd>Contains the entrypoint of the project. It has the settings, route definitions, and list of enabled apps.</dd> + +<dt>/page/</dt> +<dd>This is a demo app that contains possible common pages across projects.</dd> + +<dt>/templ/</dt> +<dd>Contains all the template files.</dd> + +<dt>/static/</dt> +<dd>Contains all the static files.</dd> + +<dt>/.ex/</dt> +<dd>Contains all the example files needed to bootstrap development or production stage.</dt> + +<dt>/pyproject.toml, /poetry.lock +<dd>Dependency management files.</dd> + +<dt>/manage.py</dt> +<dd>Contains the Django-specific commands.</dd> + +<dt>/.editorconfig</dt> +<dd>You know what to do!</dd> + +<dt>/Makefile</dt> +<dd>It has common shortcuts to manage the project. Checkout the «Make Targets» section.</dd> +</dl> + + +## Make Targets +Here is a list of make(1) targets: + +<dl> +<dt>all, or the default target</dt> +<dd>It just runs the project.</dd> + +<dt>dev-deps</dt> +<dd>Installs all the development dependencies.</dd> + +<dt>prod-deps</dt> +<dd>Installs all the production dependencies.</dd> + +<dt>sh</dt> +<dd>A shortcut for the «shell» command in manage.py.</dd> + +<dt>migrate</dt> +<dd>Runs the «migrate» command in manage.py.</dd> + +<dt>static</dt> +<dd>Runs the «collectstatic» command in manage.py.</dd> +</dl> diff --git a/base/__init__.py b/base/__init__.py diff --git a/base/asgi.py b/base/asgi.py @@ -0,0 +1,7 @@ +import os + +from django.core.asgi import get_asgi_application + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "base.settings.common") +application = get_asgi_application() diff --git a/base/settings/__init__.py b/base/settings/__init__.py @@ -0,0 +1 @@ + diff --git a/base/settings/common.py b/base/settings/common.py @@ -0,0 +1,106 @@ +from pathlib import Path + + +BASE_DIR = Path(__file__).resolve().parent.parent.parent + +# must be after BASE_DIR (to prevent circular import) +try: + from .prod import * +except ImportError: + from .dev import * + + +# apps +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + + "base", + "page", +] + +if DEBUG: + INSTALLED_APPS.append("debug_toolbar") + + +# middleware +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", +] + +if DEBUG: + MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware") + + +# wsgi app object +WSGI_APPLICATION = "base.wsgi.application" + + +# routing and templating +ROOT_URLCONF = "base.urls" + +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [BASE_DIR / "templ"], + "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", + ], + "builtins": ["django.templatetags.static"], + }, + }, +] + + +# passwd 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", + }, +] + + +# i18n +LANGUAGE_CODE = "tr-tr" +TIME_ZONE = "Europe/Istanbul" +USE_I18N = True +USE_L10N = True +USE_TZ = True + + +# assets/static files +STATICFILES_DIRS = [BASE_DIR / "static"] + +STATIC_URL = "/static/" +STATIC_ROOT = BASE_DIR / "asset/static" + +MEDIA_URL = "/media/" +MEDIA_ROOT = BASE_DIR / "asset/media" + + +# default pk type +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/base/urls.py b/base/urls.py @@ -0,0 +1,20 @@ +from django.conf import settings +from django.conf.urls.static import static +from django.contrib import admin +from django.urls import path, include +from django.shortcuts import redirect + + +urlpatterns = [ + path("", lambda _: redirect("page:home", permanent=True)), + path("yonetici/", admin.site.urls), + path("sayfa/", include("page.urls")), +] + +if settings.DEBUG: + import debug_toolbar + + urlpatterns += [ + path("__debug__/", include(debug_toolbar.urls)), + ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + diff --git a/base/wsgi.py b/base/wsgi.py @@ -0,0 +1,7 @@ +import os + +from django.core.wsgi import get_wsgi_application + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "base.settings.common") +application = get_wsgi_application() diff --git a/manage.py b/manage.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "base.settings.common") + try: + from django.core.management import execute_from_command_line + from django.core.management.commands.runserver import Command as runserver + from base.settings import common + 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 + runserver.default_port = getattr(common, "PORT", "8000") + execute_from_command_line(sys.argv) + + +if __name__ == "__main__": + main() diff --git a/page/__init__.py b/page/__init__.py diff --git a/page/admin.py b/page/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/page/apps.py b/page/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PageConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "page" diff --git a/page/migrations/__init__.py b/page/migrations/__init__.py diff --git a/page/models.py b/page/models.py @@ -0,0 +1 @@ +from django.db import models diff --git a/page/tests.py b/page/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/page/urls.py b/page/urls.py @@ -0,0 +1,12 @@ +from django.urls import path + +from . import views as v + + +app_name = "page" + +urlpatterns = [ + path("ana-sayfa/", v.home, name="home"), + path("hakkimizda/", v.about, name="about"), + path("iletisim/", v.contact, name="contact"), +] diff --git a/page/views.py b/page/views.py @@ -0,0 +1,11 @@ +from django.shortcuts import render + + +def home(r): + return render(r, "page/home.html") + +def about(r): + return render(r, "page/about.html") + +def contact(r): + return render(r, "page/contact.html") diff --git a/poetry.lock b/poetry.lock @@ -0,0 +1,119 @@ +[[package]] +name = "asgiref" +version = "3.4.0" +description = "ASGI specs, helper code, and adapters" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = "*", markers = "python_version < \"3.8\""} + +[package.extras] +tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] + +[[package]] +name = "django" +version = "3.2.4" +description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +asgiref = ">=3.3.2,<4" +pytz = "*" +sqlparse = ">=0.2.2" + +[package.extras] +argon2 = ["argon2-cffi (>=19.1.0)"] +bcrypt = ["bcrypt"] + +[[package]] +name = "django-debug-toolbar" +version = "3.2.1" +description = "A configurable set of panels that display various debug information about the current request/response." +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +Django = ">=2.2" +sqlparse = ">=0.2.0" + +[[package]] +name = "gunicorn" +version = "20.1.0" +description = "WSGI HTTP Server for UNIX" +category = "main" +optional = true +python-versions = ">=3.5" + +[package.extras] +eventlet = ["eventlet (>=0.24.1)"] +gevent = ["gevent (>=1.4.0)"] +setproctitle = ["setproctitle"] +tornado = ["tornado (>=0.2)"] + +[[package]] +name = "pytz" +version = "2021.1" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "sqlparse" +version = "0.4.1" +description = "A non-validating SQL parser." +category = "main" +optional = false +python-versions = ">=3.5" + +[[package]] +name = "typing-extensions" +version = "3.10.0.0" +description = "Backported and Experimental Type Hints for Python 3.5+" +category = "main" +optional = false +python-versions = "*" + +[extras] +wsgi = ["gunicorn"] + +[metadata] +lock-version = "1.1" +python-versions = "^3.6" +content-hash = "cfb60b5f983299a6b29cd06a858b656c93972f586a78baecbdaa421c77043575" + +[metadata.files] +asgiref = [ + {file = "asgiref-3.4.0-py3-none-any.whl", hash = "sha256:d36fa91dd90e3aa3c81a6bd426ccc8fb20bd3d22b0cf14a12800289e9c3e2563"}, + {file = "asgiref-3.4.0.tar.gz", hash = "sha256:05914d0fa65a21711e732adc6572edad6c8da5f1435c3f0c060689ced5e85195"}, +] +django = [ + {file = "Django-3.2.4-py3-none-any.whl", hash = "sha256:ea735cbbbb3b2fba6d4da4784a0043d84c67c92f1fdf15ad6db69900e792c10f"}, + {file = "Django-3.2.4.tar.gz", hash = "sha256:66c9d8db8cc6fe938a28b7887c1596e42d522e27618562517cc8929eb7e7f296"}, +] +django-debug-toolbar = [ + {file = "django-debug-toolbar-3.2.1.tar.gz", hash = "sha256:a5ff2a54f24bf88286f9872836081078f4baa843dc3735ee88524e89f8821e33"}, + {file = "django_debug_toolbar-3.2.1-py3-none-any.whl", hash = "sha256:e759e63e3fe2d3110e0e519639c166816368701eab4a47fed75d7de7018467b9"}, +] +gunicorn = [ + {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, + {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, +] +pytz = [ + {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, + {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, +] +sqlparse = [ + {file = "sqlparse-0.4.1-py3-none-any.whl", hash = "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0"}, + {file = "sqlparse-0.4.1.tar.gz", hash = "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"}, +] +typing-extensions = [ + {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"}, + {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"}, + {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"}, +] diff --git a/pyproject.toml b/pyproject.toml @@ -0,0 +1,20 @@ +[tool.poetry] +name = "djbase" +version = "0.1.0" +description = "django base" +authors = ["srfsh <srfsh@sonu.ch>"] + +[tool.poetry.dependencies] +python = "^3.6" +Django = "^3.2.4" +gunicorn = {version = "^20.1.0", optional = true} + +[tool.poetry.dev-dependencies] +django-debug-toolbar = {version = "^3.2.1"} + +[tool.poetry.extras] +wsgi = ["gunicorn"] + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/static/base/css/style.css b/static/base/css/style.css diff --git a/static/base/img/icon.ico b/static/base/img/icon.ico Binary files differ. diff --git a/static/base/js/script.js b/static/base/js/script.js diff --git a/templ/base/footer.html b/templ/base/footer.html @@ -0,0 +1,3 @@ +<footer> + &copy; 2021 +</footer> diff --git a/templ/base/layout.html b/templ/base/layout.html @@ -0,0 +1,16 @@ +<!doctype html> +<html lang="tr-tr"> +<head> + <meta charset="utf-8"/> + <title>Djang Base</title> + <meta name="viewport" content="width=device-width, initial-scale=1"/> + <link rel="icon" href="{% static 'base/img/icon.ico' %}"/> + <link rel="stylesheet" href="{% static 'base/css/style.css' %}"/> + <script defer src="{% static 'base/js/script.js' %}"></script> +</head> +<body> + {% include "base/navbar.html" %} + <main>{% block main %}{% endblock %}</main> + {% include "base/footer.html" %} +</body> +</html> diff --git a/templ/base/navbar.html b/templ/base/navbar.html @@ -0,0 +1,7 @@ +<nav> + <ul> + <li><a href="{% url 'page:home' %}">home</a></li> + <li><a href="{% url 'page:contact' %}">contact</a></li> + <li><a href="{% url 'page:about' %}">about</a></li> + </ul> +</nav> diff --git a/templ/page/about.html b/templ/page/about.html @@ -0,0 +1,5 @@ +{% extends "base/layout.html" %} + +{% block main %} +about us +{% endblock %} diff --git a/templ/page/contact.html b/templ/page/contact.html @@ -0,0 +1,5 @@ +{% extends "base/layout.html" %} + +{% block main %} +<p>contact me: <a href="mailto:awesome@example.com">my awesome email address</a></p> +{% endblock %} diff --git a/templ/page/home.html b/templ/page/home.html @@ -0,0 +1,6 @@ +{% extends "base/layout.html" %} + +{% block main %} +<h1>title</h1> +<p>paragraph</p> +{% endblock %}