├── core ├── __init__.py ├── migrations │ ├── __init__.py │ └── 0001_initial.py ├── admin.py ├── tests.py ├── urls.py ├── apps.py ├── models.py ├── views.py └── templates │ └── core │ ├── index.html │ ├── base.html │ └── navbar.html ├── htmx_websockets ├── __init__.py ├── asgi.py ├── urls.py ├── wsgi.py └── settings.py ├── .gitignore ├── requirements.txt └── manage.py /core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /htmx_websockets/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.pyc 3 | db.sqlite3 4 | notes.txt -------------------------------------------------------------------------------- /core/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /core/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==4.1.6 2 | django-allauth==0.52.0 3 | django-extensions==3.2.1 -------------------------------------------------------------------------------- /core/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | urlpatterns = [ 5 | path('', views.index, name='index') 6 | ] -------------------------------------------------------------------------------- /core/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoreConfig(AppConfig): 5 | default_auto_field = "django.db.models.BigAutoField" 6 | name = "core" 7 | -------------------------------------------------------------------------------- /core/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | # Create your models here. 5 | class User(AbstractUser): 6 | pass -------------------------------------------------------------------------------- /core/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | def index(request): 5 | context = {} 6 | return render(request, 'core/index.html', context) -------------------------------------------------------------------------------- /htmx_websockets/asgi.py: -------------------------------------------------------------------------------- 1 | import os 2 | from django.core.asgi import get_asgi_application 3 | 4 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "htmx_websockets.settings") 5 | 6 | application = get_asgi_application() -------------------------------------------------------------------------------- /htmx_websockets/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path, include 3 | 4 | urlpatterns = [ 5 | path("admin/", admin.site.urls), 6 | path('', include('core.urls')), 7 | path('accounts/', include('allauth.urls')), 8 | ] 9 | -------------------------------------------------------------------------------- /core/templates/core/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |

Welcome!

7 | 8 |

Here, there be sockets.

9 | 10 |
11 | {% endblock %} 12 | 13 | -------------------------------------------------------------------------------- /htmx_websockets/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx_websockets project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "htmx_websockets.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "htmx_websockets.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /core/templates/core/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Django and HTMX - WebSockets 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% block head %} 17 | 18 | {% endblock %} 19 | 20 | 21 | 22 | 23 | {% include 'core/navbar.html' %} 24 | 25 |
26 | {% block content %} 27 | {% endblock %} 28 |
29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /htmx_websockets/settings.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 4 | BASE_DIR = Path(__file__).resolve().parent.parent 5 | 6 | 7 | # Quick-start development settings - unsuitable for production 8 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 9 | 10 | # SECURITY WARNING: keep the secret key used in production secret! 11 | SECRET_KEY = "django-insecure-q@1(jq6-v=_3f=!^lbwhg)_16rn7c*bdu_j1*c4y18z!t_2gqv" 12 | 13 | # SECURITY WARNING: don't run with debug turned on in production! 14 | DEBUG = True 15 | 16 | ALLOWED_HOSTS = [] 17 | 18 | 19 | # Application definition 20 | 21 | INSTALLED_APPS = [ 22 | "django.contrib.admin", 23 | "django.contrib.auth", 24 | "django.contrib.contenttypes", 25 | "django.contrib.sessions", 26 | "django.contrib.messages", 27 | "django.contrib.staticfiles", 28 | "django_extensions", 29 | "core", 30 | "allauth", 31 | "allauth.account", 32 | "allauth.socialaccount", 33 | ] 34 | 35 | MIDDLEWARE = [ 36 | "django.middleware.security.SecurityMiddleware", 37 | "django.contrib.sessions.middleware.SessionMiddleware", 38 | "django.middleware.common.CommonMiddleware", 39 | "django.middleware.csrf.CsrfViewMiddleware", 40 | "django.contrib.auth.middleware.AuthenticationMiddleware", 41 | "django.contrib.messages.middleware.MessageMiddleware", 42 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 43 | ] 44 | 45 | ROOT_URLCONF = "htmx_websockets.urls" 46 | 47 | TEMPLATES = [ 48 | { 49 | "BACKEND": "django.template.backends.django.DjangoTemplates", 50 | "DIRS": [], 51 | "APP_DIRS": True, 52 | "OPTIONS": { 53 | "context_processors": [ 54 | "django.template.context_processors.debug", 55 | "django.template.context_processors.request", 56 | "django.contrib.auth.context_processors.auth", 57 | "django.contrib.messages.context_processors.messages", 58 | ], 59 | }, 60 | }, 61 | ] 62 | 63 | WSGI_APPLICATION = "htmx_websockets.wsgi.application" 64 | 65 | 66 | # Database 67 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 68 | 69 | DATABASES = { 70 | "default": { 71 | "ENGINE": "django.db.backends.sqlite3", 72 | "NAME": BASE_DIR / "db.sqlite3", 73 | } 74 | } 75 | 76 | 77 | # Password validation 78 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 79 | 80 | AUTH_PASSWORD_VALIDATORS = [ 81 | { 82 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 83 | }, 84 | { 85 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", 86 | }, 87 | { 88 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", 89 | }, 90 | { 91 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", 92 | }, 93 | ] 94 | 95 | 96 | # Internationalization 97 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 98 | 99 | LANGUAGE_CODE = "en-us" 100 | 101 | TIME_ZONE = "UTC" 102 | 103 | USE_I18N = True 104 | 105 | USE_TZ = True 106 | 107 | 108 | # Static files (CSS, JavaScript, Images) 109 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 110 | 111 | STATIC_URL = "static/" 112 | 113 | # Default primary key field type 114 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 115 | 116 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 117 | 118 | AUTH_USER_MODEL = 'core.User' 119 | 120 | SITE_ID = 1 121 | 122 | ACCOUNT_EMAIL_VERIFICATION = 'none' 123 | LOGIN_REDIRECT_URL = 'index' 124 | -------------------------------------------------------------------------------- /core/templates/core/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.6 on 2023-02-06 09:03 2 | 3 | import django.contrib.auth.models 4 | import django.contrib.auth.validators 5 | from django.db import migrations, models 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ("auth", "0012_alter_user_first_name_max_length"), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name="User", 20 | fields=[ 21 | ( 22 | "id", 23 | models.BigAutoField( 24 | auto_created=True, 25 | primary_key=True, 26 | serialize=False, 27 | verbose_name="ID", 28 | ), 29 | ), 30 | ("password", models.CharField(max_length=128, verbose_name="password")), 31 | ( 32 | "last_login", 33 | models.DateTimeField( 34 | blank=True, null=True, verbose_name="last login" 35 | ), 36 | ), 37 | ( 38 | "is_superuser", 39 | models.BooleanField( 40 | default=False, 41 | help_text="Designates that this user has all permissions without explicitly assigning them.", 42 | verbose_name="superuser status", 43 | ), 44 | ), 45 | ( 46 | "username", 47 | models.CharField( 48 | error_messages={ 49 | "unique": "A user with that username already exists." 50 | }, 51 | help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", 52 | max_length=150, 53 | unique=True, 54 | validators=[ 55 | django.contrib.auth.validators.UnicodeUsernameValidator() 56 | ], 57 | verbose_name="username", 58 | ), 59 | ), 60 | ( 61 | "first_name", 62 | models.CharField( 63 | blank=True, max_length=150, verbose_name="first name" 64 | ), 65 | ), 66 | ( 67 | "last_name", 68 | models.CharField( 69 | blank=True, max_length=150, verbose_name="last name" 70 | ), 71 | ), 72 | ( 73 | "email", 74 | models.EmailField( 75 | blank=True, max_length=254, verbose_name="email address" 76 | ), 77 | ), 78 | ( 79 | "is_staff", 80 | models.BooleanField( 81 | default=False, 82 | help_text="Designates whether the user can log into this admin site.", 83 | verbose_name="staff status", 84 | ), 85 | ), 86 | ( 87 | "is_active", 88 | models.BooleanField( 89 | default=True, 90 | help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", 91 | verbose_name="active", 92 | ), 93 | ), 94 | ( 95 | "date_joined", 96 | models.DateTimeField( 97 | default=django.utils.timezone.now, verbose_name="date joined" 98 | ), 99 | ), 100 | ( 101 | "groups", 102 | models.ManyToManyField( 103 | blank=True, 104 | help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", 105 | related_name="user_set", 106 | related_query_name="user", 107 | to="auth.group", 108 | verbose_name="groups", 109 | ), 110 | ), 111 | ( 112 | "user_permissions", 113 | models.ManyToManyField( 114 | blank=True, 115 | help_text="Specific permissions for this user.", 116 | related_name="user_set", 117 | related_query_name="user", 118 | to="auth.permission", 119 | verbose_name="user permissions", 120 | ), 121 | ), 122 | ], 123 | options={ 124 | "verbose_name": "user", 125 | "verbose_name_plural": "users", 126 | "abstract": False, 127 | }, 128 | managers=[ 129 | ("objects", django.contrib.auth.models.UserManager()), 130 | ], 131 | ), 132 | ] 133 | --------------------------------------------------------------------------------