├── Starter ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── index.html │ │ ├── partials │ │ │ └── navbar.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #1 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── index.html │ │ ├── partials │ │ │ └── navbar.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #2 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── index.html │ │ ├── partials │ │ │ └── navbar.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #3 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-list.html │ │ │ └── navbar.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── media │ └── film_photos │ │ ├── fargo.jpg │ │ ├── fargo_Er2yaWQ.jpg │ │ ├── fargo_jaCbgFc.jpg │ │ ├── godfather.jpg │ │ ├── godfather_Vszgv8p.jpg │ │ ├── no_country_for_old_men.jpg │ │ └── no_country_for_old_men_sxy3ETB.jpg ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #4 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-list.html │ │ │ └── navbar.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── media │ └── film_photos │ │ ├── fargo.jpg │ │ ├── fargo_Er2yaWQ.jpg │ │ ├── fargo_jaCbgFc.jpg │ │ ├── godfather.jpg │ │ ├── godfather_Vszgv8p.jpg │ │ ├── no_country_for_old_men.jpg │ │ └── no_country_for_old_men_sxy3ETB.jpg ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #5 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ ├── 0003_alter_film_name.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-list.html │ │ │ ├── navbar.html │ │ │ ├── search-results.html │ │ │ └── search.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── media │ └── film_photos │ │ ├── fargo.jpg │ │ ├── fargo_Er2yaWQ.jpg │ │ ├── fargo_jaCbgFc.jpg │ │ ├── godfather.jpg │ │ ├── godfather_Vszgv8p.jpg │ │ ├── no_country_for_old_men.jpg │ │ └── no_country_for_old_men_sxy3ETB.jpg ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #6.1 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── fixtures │ │ └── films.json │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ ├── 0003_alter_film_name.py │ │ ├── 0004_auto_20211108_1854.py │ │ ├── 0005_alter_film_users.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-list.html │ │ │ ├── navbar.html │ │ │ ├── search-results.html │ │ │ └── search.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── media │ └── film_photos │ │ ├── fargo.jpg │ │ ├── fargo_Er2yaWQ.jpg │ │ ├── fargo_jaCbgFc.jpg │ │ ├── godfather.jpg │ │ ├── godfather_Vszgv8p.jpg │ │ ├── no_country_for_old_men.jpg │ │ └── no_country_for_old_men_sxy3ETB.jpg ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #6.2 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── fixtures │ │ └── films.json │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ ├── 0003_alter_film_name.py │ │ ├── 0004_auto_20211108_1854.py │ │ ├── 0005_alter_film_users.py │ │ ├── 0006_film_photo.py │ │ ├── 0007_alter_film_photo.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-detail.html │ │ │ ├── film-list.html │ │ │ ├── navbar.html │ │ │ ├── search-results.html │ │ │ └── search.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #7 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── fixtures │ │ └── films.json │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ ├── 0003_alter_film_name.py │ │ ├── 0004_auto_20211108_1854.py │ │ ├── 0005_alter_film_users.py │ │ ├── 0006_film_photo.py │ │ ├── 0007_alter_film_photo.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-detail.html │ │ │ ├── film-list.html │ │ │ ├── navbar.html │ │ │ ├── search-results.html │ │ │ └── search.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ └── css │ └── styles.css ├── Video #8 ├── .gitignore ├── films │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── fixtures │ │ └── films.json │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_film.py │ │ ├── 0003_alter_film_name.py │ │ ├── 0004_auto_20211108_1854.py │ │ ├── 0005_alter_film_users.py │ │ ├── 0006_film_photo.py │ │ ├── 0007_alter_film_photo.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── base.html │ │ ├── films.html │ │ ├── index.html │ │ ├── partials │ │ │ ├── film-detail.html │ │ │ ├── film-list-elements.html │ │ │ ├── film-list.html │ │ │ ├── navbar.html │ │ │ ├── search-results.html │ │ │ └── search.html │ │ └── registration │ │ │ ├── login.html │ │ │ └── register.html │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── htmx │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── requirements.txt └── static │ └── css │ └── styles.css └── Video #9 ├── .gitignore ├── films ├── __init__.py ├── admin.py ├── apps.py ├── fixtures │ └── films.json ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_film.py │ ├── 0003_alter_film_name.py │ ├── 0004_auto_20211108_1854.py │ ├── 0005_alter_film_users.py │ ├── 0006_film_photo.py │ ├── 0007_alter_film_photo.py │ └── __init__.py ├── models.py ├── templates │ ├── base.html │ ├── films.html │ ├── index.html │ ├── partials │ │ ├── film-detail.html │ │ ├── film-list-elements.html │ │ ├── film-list.html │ │ ├── navbar.html │ │ ├── search-results.html │ │ └── search.html │ └── registration │ │ ├── login.html │ │ └── register.html ├── tests.py ├── urls.py ├── utils.py └── views.py ├── htmx ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── manage.py ├── requirements.txt └── static └── css └── styles.css /Starter/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/ -------------------------------------------------------------------------------- /Starter/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Starter/films/__init__.py -------------------------------------------------------------------------------- /Starter/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Starter/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Starter/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Starter/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Starter/films/migrations/__init__.py -------------------------------------------------------------------------------- /Starter/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | class User(AbstractUser): 5 | pass -------------------------------------------------------------------------------- /Starter/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% include 'partials/navbar.html' %} 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /Starter/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Starter/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Starter/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Login

7 |
8 |
9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
17 | {% endfor %} 18 | 19 | 20 |
21 |
22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Starter/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Register

7 |
8 |
9 | {% csrf_token %} 10 | 11 |
12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" %} 15 | 16 | 17 | {{ form.password1.errors }} 18 | {% render_field form.password1 class="form-control" %} 19 | 20 | 21 | {{ form.password2.errors }} 22 | {% render_field form.password2 class="form-control" %} 23 |
24 | 25 | 26 |
27 |
28 | {% endblock content %} 29 | -------------------------------------------------------------------------------- /Starter/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Starter/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register") 10 | ] 11 | -------------------------------------------------------------------------------- /Starter/films/views.py: -------------------------------------------------------------------------------- 1 | from django.http.response import HttpResponse, HttpResponsePermanentRedirect 2 | from django.shortcuts import render 3 | from django.contrib.auth.views import LoginView 4 | from django.urls import reverse_lazy 5 | from django.views.generic import FormView, TemplateView 6 | from django.contrib.auth import get_user_model 7 | 8 | from films.forms import RegisterForm 9 | 10 | # Create your views here. 11 | class IndexView(TemplateView): 12 | template_name = 'index.html' 13 | 14 | class Login(LoginView): 15 | template_name = 'registration/login.html' 16 | 17 | class RegisterView(FormView): 18 | form_class = RegisterForm 19 | template_name = 'registration/register.html' 20 | success_url = reverse_lazy('login') 21 | 22 | def form_valid(self, form): 23 | form.save() # save the user 24 | return super().form_valid(form) -------------------------------------------------------------------------------- /Starter/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Starter/htmx/__init__.py -------------------------------------------------------------------------------- /Starter/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Starter/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Starter/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Starter/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.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 | -------------------------------------------------------------------------------- /Starter/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Starter/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | -------------------------------------------------------------------------------- /Video #1/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/ -------------------------------------------------------------------------------- /Video #1/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #1/films/__init__.py -------------------------------------------------------------------------------- /Video #1/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #1/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #1/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #1/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #1/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #1/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | class User(AbstractUser): 5 | pass -------------------------------------------------------------------------------- /Video #1/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% include 'partials/navbar.html' %} 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /Video #1/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #1/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #1/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Login

7 |
8 |
9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
17 | {% endfor %} 18 | 19 | 20 |
21 |
22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #1/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Register

7 |
8 |
9 | {% csrf_token %} 10 | 11 |
12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username hx-post="/check-username/" hx-target="#username-err" hx-trigger="keyup" class="form-control" %} 15 |
16 |
17 |
18 | 19 | 20 | {{ form.password1.errors }} 21 | {% render_field form.password1 class="form-control" %} 22 |
23 |
24 | 25 | {{ form.password2.errors }} 26 | {% render_field form.password2 class="form-control" %} 27 |
28 | 29 | 30 |
31 |
32 | {% endblock content %} 33 | -------------------------------------------------------------------------------- /Video #1/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #1/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | ] 11 | 12 | hmtx_views = [ 13 | path("check-username/", views.check_username, name='check-username'), 14 | ] 15 | 16 | urlpatterns += hmtx_views 17 | -------------------------------------------------------------------------------- /Video #1/films/views.py: -------------------------------------------------------------------------------- 1 | from django.http.response import HttpResponse, HttpResponsePermanentRedirect 2 | from django.shortcuts import render 3 | from django.contrib.auth import get_user_model 4 | from django.contrib.auth.views import LoginView 5 | from django.urls import reverse_lazy 6 | from django.http import HttpResponse 7 | from django.views.generic import FormView, TemplateView 8 | from django.contrib.auth import get_user_model 9 | 10 | from films.forms import RegisterForm 11 | 12 | # Create your views here. 13 | class IndexView(TemplateView): 14 | template_name = 'index.html' 15 | 16 | class Login(LoginView): 17 | template_name = 'registration/login.html' 18 | 19 | class RegisterView(FormView): 20 | form_class = RegisterForm 21 | template_name = 'registration/register.html' 22 | success_url = reverse_lazy('login') 23 | 24 | def form_valid(self, form): 25 | form.save() # save the user 26 | return super().form_valid(form) 27 | 28 | def check_username(request): 29 | username = request.POST.get('username') 30 | if get_user_model().objects.filter(username=username).exists(): 31 | return HttpResponse("This username already exists") 32 | else: 33 | return HttpResponse("") -------------------------------------------------------------------------------- /Video #1/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #1/htmx/__init__.py -------------------------------------------------------------------------------- /Video #1/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #1/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Video #1/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #1/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.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 | -------------------------------------------------------------------------------- /Video #1/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #1/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | -------------------------------------------------------------------------------- /Video #2/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/ -------------------------------------------------------------------------------- /Video #2/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #2/films/__init__.py -------------------------------------------------------------------------------- /Video #2/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #2/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #2/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #2/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #2/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #2/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | class User(AbstractUser): 5 | pass -------------------------------------------------------------------------------- /Video #2/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% include 'partials/navbar.html' %} 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /Video #2/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #2/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #2/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Login

7 |
8 |
9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
17 | {% endfor %} 18 | 19 | 20 |
21 |
22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #2/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Register

7 |
8 |
9 | {% csrf_token %} 10 | 11 |
12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
25 | 26 | 27 |
28 |
29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #2/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #2/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register") 10 | ] 11 | 12 | htmx_urlpatterns = [ 13 | path('check_username/', views.check_username, name='check-username') 14 | ] 15 | 16 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #2/films/views.py: -------------------------------------------------------------------------------- 1 | from django.http.response import HttpResponse, HttpResponsePermanentRedirect 2 | from django.shortcuts import render 3 | from django.contrib.auth.views import LoginView 4 | from django.urls import reverse_lazy 5 | from django.views.generic import FormView, TemplateView 6 | from django.contrib.auth import get_user_model 7 | 8 | from films.forms import RegisterForm 9 | 10 | # Create your views here. 11 | class IndexView(TemplateView): 12 | template_name = 'index.html' 13 | 14 | class Login(LoginView): 15 | template_name = 'registration/login.html' 16 | 17 | class RegisterView(FormView): 18 | form_class = RegisterForm 19 | template_name = 'registration/register.html' 20 | success_url = reverse_lazy('login') 21 | 22 | def form_valid(self, form): 23 | form.save() # save the user 24 | return super().form_valid(form) 25 | 26 | def check_username(request): 27 | username = request.POST.get('username') 28 | if get_user_model().objects.filter(username=username).exists(): 29 | return HttpResponse("
This username already exists
") 30 | else: 31 | return HttpResponse("
This username is available
") -------------------------------------------------------------------------------- /Video #2/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #2/htmx/__init__.py -------------------------------------------------------------------------------- /Video #2/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #2/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Video #2/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #2/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.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 | -------------------------------------------------------------------------------- /Video #2/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #2/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } 16 | -------------------------------------------------------------------------------- /Video #3/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt -------------------------------------------------------------------------------- /Video #3/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/films/__init__.py -------------------------------------------------------------------------------- /Video #3/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #3/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #3/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #3/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #3/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #3/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | class User(AbstractUser): 5 | pass 6 | 7 | class Film(models.Model): 8 | name = models.CharField(max_length=128) 9 | users = models.ManyToManyField(User, related_name='films') -------------------------------------------------------------------------------- /Video #3/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% include 'partials/navbar.html' %} 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /Video #3/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
5 |
6 |

My Films

7 |
8 | {% csrf_token %} 9 | 10 | 11 |
12 |
13 |
14 | 15 |
16 | {% include 'partials/film-list.html' %} 17 |
18 |
19 | {% endblock content %} -------------------------------------------------------------------------------- /Video #3/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #3/films/templates/partials/film-list.html: -------------------------------------------------------------------------------- 1 | {% if films %} 2 | 7 | {% else %} 8 |

You do not have any films in your list

9 | {% endif %} -------------------------------------------------------------------------------- /Video #3/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #3/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Login

7 |
8 |
9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
17 | {% endfor %} 18 | 19 | 20 |
21 |
22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #3/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Register

7 |
8 |
9 | {% csrf_token %} 10 | 11 |
12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
25 | 26 | 27 |
28 |
29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #3/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #3/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film') 16 | ] 17 | 18 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #3/films/views.py: -------------------------------------------------------------------------------- 1 | from django.http.response import HttpResponse, HttpResponsePermanentRedirect 2 | from django.shortcuts import render 3 | from django.contrib.auth.views import LoginView 4 | from django.urls import reverse_lazy 5 | from django.views.generic import FormView, TemplateView 6 | from django.contrib.auth import get_user_model 7 | 8 | from films.forms import RegisterForm 9 | from films.models import Film 10 | from django.views.generic.list import ListView 11 | 12 | # Create your views here. 13 | class IndexView(TemplateView): 14 | template_name = 'index.html' 15 | 16 | class Login(LoginView): 17 | template_name = 'registration/login.html' 18 | 19 | class RegisterView(FormView): 20 | form_class = RegisterForm 21 | template_name = 'registration/register.html' 22 | success_url = reverse_lazy('login') 23 | 24 | def form_valid(self, form): 25 | form.save() # save the user 26 | return super().form_valid(form) 27 | 28 | 29 | class FilmList(ListView): 30 | template_name = 'films.html' 31 | model = Film 32 | context_object_name = 'films' 33 | 34 | def get_queryset(self): 35 | user = self.request.user 36 | return user.films.all() 37 | 38 | 39 | def check_username(request): 40 | username = request.POST.get('username') 41 | if get_user_model().objects.filter(username=username).exists(): 42 | return HttpResponse("
This username already exists
") 43 | else: 44 | return HttpResponse("
This username is available
") 45 | 46 | def add_film(request): 47 | name = request.POST.get('filmname') 48 | 49 | # add film 50 | film = Film.objects.create(name=name) 51 | 52 | # add the film to the user's list 53 | request.user.films.add(film) 54 | 55 | # return template fragment with all the user's films 56 | films = request.user.films.all() 57 | return render(request, 'partials/film-list.html', {'films': films}) -------------------------------------------------------------------------------- /Video #3/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/htmx/__init__.py -------------------------------------------------------------------------------- /Video #3/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #3/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Video #3/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #3/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.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 | -------------------------------------------------------------------------------- /Video #3/media/film_photos/fargo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/fargo.jpg -------------------------------------------------------------------------------- /Video #3/media/film_photos/fargo_Er2yaWQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/fargo_Er2yaWQ.jpg -------------------------------------------------------------------------------- /Video #3/media/film_photos/fargo_jaCbgFc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/fargo_jaCbgFc.jpg -------------------------------------------------------------------------------- /Video #3/media/film_photos/godfather.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/godfather.jpg -------------------------------------------------------------------------------- /Video #3/media/film_photos/godfather_Vszgv8p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/godfather_Vszgv8p.jpg -------------------------------------------------------------------------------- /Video #3/media/film_photos/no_country_for_old_men.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/no_country_for_old_men.jpg -------------------------------------------------------------------------------- /Video #3/media/film_photos/no_country_for_old_men_sxy3ETB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #3/media/film_photos/no_country_for_old_men_sxy3ETB.jpg -------------------------------------------------------------------------------- /Video #3/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #3/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #4/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt -------------------------------------------------------------------------------- /Video #4/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/films/__init__.py -------------------------------------------------------------------------------- /Video #4/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #4/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #4/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #4/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #4/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #4/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | class User(AbstractUser): 5 | pass 6 | 7 | class Film(models.Model): 8 | name = models.CharField(max_length=128, unique=True) 9 | users = models.ManyToManyField(User, related_name='films') -------------------------------------------------------------------------------- /Video #4/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% include 'partials/navbar.html' %} 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 38 | 39 | -------------------------------------------------------------------------------- /Video #4/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
5 |
6 |

My Films

7 |
8 | {% csrf_token %} 9 | 10 | 11 |
12 |
13 |
14 | 15 |
16 | {% include 'partials/film-list.html' %} 17 |
18 |
19 | {% endblock content %} -------------------------------------------------------------------------------- /Video #4/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #4/films/templates/partials/film-list.html: -------------------------------------------------------------------------------- 1 | {% if films %} 2 | 3 | {% csrf_token %} 4 | 16 | {% else %} 17 |

You do not have any films in your list

18 | {% endif %} -------------------------------------------------------------------------------- /Video #4/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #4/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Login

7 |
8 |
9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
17 | {% endfor %} 18 | 19 | 20 |
21 |
22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #4/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Register

7 |
8 |
9 | {% csrf_token %} 10 | 11 |
12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
25 | 26 | 27 |
28 |
29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #4/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #4/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film') 17 | ] 18 | 19 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #4/films/views.py: -------------------------------------------------------------------------------- 1 | from django.http.response import HttpResponse, HttpResponsePermanentRedirect 2 | from django.shortcuts import render 3 | from django.contrib.auth.views import LoginView 4 | from django.urls import reverse_lazy 5 | from django.views.generic import FormView, TemplateView 6 | from django.contrib.auth import get_user_model 7 | 8 | from films.forms import RegisterForm 9 | from films.models import Film 10 | from django.views.generic.list import ListView 11 | 12 | # Create your views here. 13 | class IndexView(TemplateView): 14 | template_name = 'index.html' 15 | 16 | class Login(LoginView): 17 | template_name = 'registration/login.html' 18 | 19 | class RegisterView(FormView): 20 | form_class = RegisterForm 21 | template_name = 'registration/register.html' 22 | success_url = reverse_lazy('login') 23 | 24 | def form_valid(self, form): 25 | form.save() # save the user 26 | return super().form_valid(form) 27 | 28 | 29 | class FilmList(ListView): 30 | template_name = 'films.html' 31 | model = Film 32 | context_object_name = 'films' 33 | 34 | def get_queryset(self): 35 | user = self.request.user 36 | return user.films.all() 37 | 38 | 39 | def check_username(request): 40 | username = request.POST.get('username') 41 | if get_user_model().objects.filter(username=username).exists(): 42 | return HttpResponse("
This username already exists
") 43 | else: 44 | return HttpResponse("
This username is available
") 45 | 46 | def add_film(request): 47 | name = request.POST.get('filmname') 48 | 49 | # add film 50 | film = Film.objects.create(name=name) 51 | 52 | # add the film to the user's list 53 | request.user.films.add(film) 54 | 55 | # return template fragment with all the user's films 56 | films = request.user.films.all() 57 | return render(request, 'partials/film-list.html', {'films': films}) 58 | 59 | def delete_film(request, pk): 60 | # remove the film from the user's list 61 | request.user.films.remove(pk) 62 | 63 | # return template fragment with all the user's films 64 | films = request.user.films.all() 65 | return render(request, 'partials/film-list.html', {'films': films}) -------------------------------------------------------------------------------- /Video #4/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/htmx/__init__.py -------------------------------------------------------------------------------- /Video #4/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #4/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Video #4/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #4/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.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 | -------------------------------------------------------------------------------- /Video #4/media/film_photos/fargo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/fargo.jpg -------------------------------------------------------------------------------- /Video #4/media/film_photos/fargo_Er2yaWQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/fargo_Er2yaWQ.jpg -------------------------------------------------------------------------------- /Video #4/media/film_photos/fargo_jaCbgFc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/fargo_jaCbgFc.jpg -------------------------------------------------------------------------------- /Video #4/media/film_photos/godfather.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/godfather.jpg -------------------------------------------------------------------------------- /Video #4/media/film_photos/godfather_Vszgv8p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/godfather_Vszgv8p.jpg -------------------------------------------------------------------------------- /Video #4/media/film_photos/no_country_for_old_men.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/no_country_for_old_men.jpg -------------------------------------------------------------------------------- /Video #4/media/film_photos/no_country_for_old_men_sxy3ETB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #4/media/film_photos/no_country_for_old_men_sxy3ETB.jpg -------------------------------------------------------------------------------- /Video #4/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #4/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #5/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt -------------------------------------------------------------------------------- /Video #5/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/films/__init__.py -------------------------------------------------------------------------------- /Video #5/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #5/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #5/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #5/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #5/films/migrations/0003_alter_film_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-06 08:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0002_film'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='name', 16 | field=models.CharField(max_length=128, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #5/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #5/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | 4 | class User(AbstractUser): 5 | pass 6 | 7 | class Film(models.Model): 8 | name = models.CharField(max_length=128, unique=True) 9 | users = models.ManyToManyField(User, related_name='films') -------------------------------------------------------------------------------- /Video #5/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% include 'partials/navbar.html' %} 27 | 28 |
29 | {% block content %} 30 | {% endblock %} 31 |
32 | 33 | 38 | 39 | -------------------------------------------------------------------------------- /Video #5/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
5 |
6 |

My Films

7 |
8 | {% csrf_token %} 9 | 14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 | {% include 'partials/film-list.html' %} 22 |
23 |
24 |
25 | {% endblock content %} -------------------------------------------------------------------------------- /Video #5/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #5/films/templates/partials/film-list.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | {% if messages %} 6 |
    7 | {% for message in messages %} 8 | {{ message }} 9 | {% endfor %} 10 |
11 | {% endif %} 12 | 13 | {% if films %} 14 | 15 | {% csrf_token %} 16 |
    17 | {% for film in films %} 18 |
  • 19 | {{ film.name }} 20 | X 25 |
  • 26 | {% endfor %} 27 |
28 | {% else %} 29 |

You do not have any films in your list

30 | {% endif %} 31 | 32 |
33 | 34 |
35 | {% include 'partials/search.html' %} 36 |
37 |
38 | 39 | {% if request.method == 'POST' %} 40 | 46 | {% endif %} -------------------------------------------------------------------------------- /Video #5/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #5/films/templates/partials/search-results.html: -------------------------------------------------------------------------------- 1 | {% if results %} 2 | 3 | {% csrf_token %} 4 | 16 | {% else %} 17 |

No search results

18 | {% endif %} -------------------------------------------------------------------------------- /Video #5/films/templates/partials/search.html: -------------------------------------------------------------------------------- 1 |
2 | {% csrf_token %} 3 | 10 | 11 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /Video #5/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Login

7 |
8 |
9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
17 | {% endfor %} 18 | 19 | 20 |
21 |
22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #5/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
6 |

Register

7 |
8 |
9 | {% csrf_token %} 10 | 11 |
12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
25 | 26 | 27 |
28 |
29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #5/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #5/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film'), 17 | path('search-film/', views.search_film, name='search-film'), 18 | path('clear/', views.clear, name='clear') 19 | ] 20 | 21 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #5/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/htmx/__init__.py -------------------------------------------------------------------------------- /Video #5/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #5/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Video #5/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #5/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.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 | -------------------------------------------------------------------------------- /Video #5/media/film_photos/fargo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/fargo.jpg -------------------------------------------------------------------------------- /Video #5/media/film_photos/fargo_Er2yaWQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/fargo_Er2yaWQ.jpg -------------------------------------------------------------------------------- /Video #5/media/film_photos/fargo_jaCbgFc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/fargo_jaCbgFc.jpg -------------------------------------------------------------------------------- /Video #5/media/film_photos/godfather.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/godfather.jpg -------------------------------------------------------------------------------- /Video #5/media/film_photos/godfather_Vszgv8p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/godfather_Vszgv8p.jpg -------------------------------------------------------------------------------- /Video #5/media/film_photos/no_country_for_old_men.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/no_country_for_old_men.jpg -------------------------------------------------------------------------------- /Video #5/media/film_photos/no_country_for_old_men_sxy3ETB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #5/media/film_photos/no_country_for_old_men_sxy3ETB.jpg -------------------------------------------------------------------------------- /Video #5/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #5/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #6.1/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt -------------------------------------------------------------------------------- /Video #6.1/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/films/__init__.py -------------------------------------------------------------------------------- /Video #6.1/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #6.1/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #6.1/films/fixtures/films.json: -------------------------------------------------------------------------------- 1 | [{"model": "films.film", "pk": 35, "fields": {"name": "Taxi Driver"}}, {"model": "films.film", "pk": 36, "fields": {"name": "Godfather"}}, {"model": "films.film", "pk": 37, "fields": {"name": "Fargo"}}, {"model": "films.film", "pk": 38, "fields": {"name": "Big Lebowski"}}, {"model": "films.film", "pk": 39, "fields": {"name": "Mulholland Drive"}}, {"model": "films.film", "pk": 40, "fields": {"name": "Goodfellas"}}, {"model": "films.film", "pk": 41, "fields": {"name": "Raging Bull"}}, {"model": "films.film", "pk": 42, "fields": {"name": "The Shining"}}, {"model": "films.film", "pk": 43, "fields": {"name": "Chinatown"}}, {"model": "films.film", "pk": 44, "fields": {"name": "A Clockwork Orange"}}, {"model": "films.film", "pk": 45, "fields": {"name": "Dr. Strangelove"}}, {"model": "films.film", "pk": 46, "fields": {"name": "Blue Velvet"}}, {"model": "films.film", "pk": 47, "fields": {"name": "No Country for Old Men"}}, {"model": "films.film", "pk": 48, "fields": {"name": "Pulp Fiction"}}, {"model": "films.film", "pk": 49, "fields": {"name": "Escape From New York"}}, {"model": "films.film", "pk": 50, "fields": {"name": "sdgjdshgsdg"}}] 2 | -------------------------------------------------------------------------------- /Video #6.1/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #6.1/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #6.1/films/migrations/0003_alter_film_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-06 08:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0002_film'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='name', 16 | field=models.CharField(max_length=128, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #6.1/films/migrations/0004_auto_20211108_1854.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import django.db.models.functions.text 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('films', '0003_alter_film_name'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelOptions( 17 | name='film', 18 | options={'ordering': [django.db.models.functions.text.Lower('name')]}, 19 | ), 20 | migrations.CreateModel( 21 | name='UserFilms', 22 | fields=[ 23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 24 | ('order', models.PositiveSmallIntegerField()), 25 | ('film', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='films.film')), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 27 | ], 28 | options={ 29 | 'ordering': ['order'], 30 | }, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /Video #6.1/films/migrations/0005_alter_film_users.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0004_auto_20211108_1854'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='film', 16 | name='users', 17 | ), 18 | migrations.AddField( 19 | model_name='film', 20 | name='users', 21 | field=models.ManyToManyField(related_name='films', through='films.UserFilms', to=settings.AUTH_USER_MODEL), 22 | ), 23 | 24 | 25 | ] 26 | -------------------------------------------------------------------------------- /Video #6.1/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #6.1/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | from django.db.models.functions import Lower 4 | 5 | class User(AbstractUser): 6 | pass 7 | 8 | class Film(models.Model): 9 | name = models.CharField(max_length=128, unique=True) 10 | users = models.ManyToManyField(User, related_name='films', through='UserFilms') 11 | 12 | class Meta: 13 | ordering = [Lower('name')] 14 | 15 | class UserFilms(models.Model): 16 | user = models.ForeignKey(User, on_delete=models.CASCADE) 17 | film = models.ForeignKey(Film, on_delete=models.CASCADE) 18 | order = models.PositiveSmallIntegerField() 19 | 20 | class Meta: 21 | ordering = ['order'] -------------------------------------------------------------------------------- /Video #6.1/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {% include 'partials/navbar.html' %} 28 | 29 |
30 | {% block content %} 31 | {% endblock %} 32 |
33 | 34 | 50 | 51 | -------------------------------------------------------------------------------- /Video #6.1/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
5 |
6 |

My Films

7 |
8 | {% csrf_token %} 9 | 14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 | {% include 'partials/film-list.html' %} 22 |
23 |
24 |
25 | {% endblock content %} -------------------------------------------------------------------------------- /Video #6.1/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Welcome!

6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #6.1/films/templates/partials/film-list.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | {% if messages %} 6 |
    7 | {% for message in messages %} 8 | {{ message }} 9 | {% endfor %} 10 |
11 | {% endif %} 12 | 13 | {% if films %} 14 | 15 | {% csrf_token %} 16 |
17 |
Updating...
18 | {% for film in films %} 19 |
20 | 21 |
  • 22 | #{{film.order}} {{ film.film.name }} 23 | X 28 |
  • 29 |
    30 | {% endfor %} 31 |
    32 | {% else %} 33 |

    You do not have any films in your list

    34 | {% endif %} 35 | 36 |
    37 | 38 |
    39 | {% include 'partials/search.html' %} 40 |
    41 |
    42 | 43 | {% if request.method == 'POST' %} 44 | 50 | {% endif %} -------------------------------------------------------------------------------- /Video #6.1/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #6.1/films/templates/partials/search-results.html: -------------------------------------------------------------------------------- 1 | {% if results %} 2 | 3 | {% csrf_token %} 4 | 16 | {% else %} 17 |

    No search results

    18 | {% endif %} -------------------------------------------------------------------------------- /Video #6.1/films/templates/partials/search.html: -------------------------------------------------------------------------------- 1 |
    2 | {% csrf_token %} 3 | 10 | 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /Video #6.1/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Login

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
    13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
    17 | {% endfor %} 18 | 19 | 20 |
    21 |
    22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #6.1/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Register

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 |
    12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
    16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
    25 | 26 | 27 |
    28 |
    29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #6.1/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #6.1/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film'), 17 | path('search-film/', views.search_film, name='search-film'), 18 | path('clear/', views.clear, name='clear'), 19 | path('sort/', views.sort, name='sort'), 20 | ] 21 | 22 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #6.1/films/utils.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Max 2 | from films.models import UserFilms 3 | 4 | 5 | def get_max_order(user) -> int: 6 | existing_films = UserFilms.objects.filter(user=user) 7 | if not existing_films.exists(): 8 | return 1 9 | else: 10 | current_max = existing_films.aggregate(max_order=Max('order'))['max_order'] 11 | return current_max + 1 12 | 13 | def reorder(user): 14 | existing_films = UserFilms.objects.filter(user=user) 15 | if not existing_films.exists(): 16 | return 17 | number_of_films = existing_films.count() 18 | new_ordering = range(1, number_of_films+1) 19 | 20 | for order, user_film in zip(new_ordering, existing_films): 21 | user_film.order = order 22 | user_film.save() 23 | -------------------------------------------------------------------------------- /Video #6.1/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/htmx/__init__.py -------------------------------------------------------------------------------- /Video #6.1/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #6.1/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | urlpatterns = [ 5 | path('', include('films.urls')), 6 | path('admin/', admin.site.urls), 7 | ] 8 | -------------------------------------------------------------------------------- /Video #6.1/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #6.1/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.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 | -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/fargo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/fargo.jpg -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/fargo_Er2yaWQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/fargo_Er2yaWQ.jpg -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/fargo_jaCbgFc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/fargo_jaCbgFc.jpg -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/godfather.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/godfather.jpg -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/godfather_Vszgv8p.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/godfather_Vszgv8p.jpg -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/no_country_for_old_men.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/no_country_for_old_men.jpg -------------------------------------------------------------------------------- /Video #6.1/media/film_photos/no_country_for_old_men_sxy3ETB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.1/media/film_photos/no_country_for_old_men_sxy3ETB.jpg -------------------------------------------------------------------------------- /Video #6.1/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #6.1/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #6.2/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/* -------------------------------------------------------------------------------- /Video #6.2/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.2/films/__init__.py -------------------------------------------------------------------------------- /Video #6.2/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #6.2/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #6.2/films/fixtures/films.json: -------------------------------------------------------------------------------- 1 | [{"model": "films.film", "pk": 35, "fields": {"name": "Taxi Driver"}}, {"model": "films.film", "pk": 36, "fields": {"name": "Godfather"}}, {"model": "films.film", "pk": 37, "fields": {"name": "Fargo"}}, {"model": "films.film", "pk": 38, "fields": {"name": "Big Lebowski"}}, {"model": "films.film", "pk": 39, "fields": {"name": "Mulholland Drive"}}, {"model": "films.film", "pk": 40, "fields": {"name": "Goodfellas"}}, {"model": "films.film", "pk": 41, "fields": {"name": "Raging Bull"}}, {"model": "films.film", "pk": 42, "fields": {"name": "The Shining"}}, {"model": "films.film", "pk": 43, "fields": {"name": "Chinatown"}}, {"model": "films.film", "pk": 44, "fields": {"name": "A Clockwork Orange"}}, {"model": "films.film", "pk": 45, "fields": {"name": "Dr. Strangelove"}}, {"model": "films.film", "pk": 46, "fields": {"name": "Blue Velvet"}}, {"model": "films.film", "pk": 47, "fields": {"name": "No Country for Old Men"}}, {"model": "films.film", "pk": 48, "fields": {"name": "Pulp Fiction"}}, {"model": "films.film", "pk": 49, "fields": {"name": "Escape From New York"}}, {"model": "films.film", "pk": 50, "fields": {"name": "sdgjdshgsdg"}}] 2 | -------------------------------------------------------------------------------- /Video #6.2/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #6.2/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #6.2/films/migrations/0003_alter_film_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-06 08:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0002_film'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='name', 16 | field=models.CharField(max_length=128, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #6.2/films/migrations/0004_auto_20211108_1854.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import django.db.models.functions.text 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('films', '0003_alter_film_name'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelOptions( 17 | name='film', 18 | options={'ordering': [django.db.models.functions.text.Lower('name')]}, 19 | ), 20 | migrations.CreateModel( 21 | name='UserFilms', 22 | fields=[ 23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 24 | ('order', models.PositiveSmallIntegerField()), 25 | ('film', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='films.film')), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 27 | ], 28 | options={ 29 | 'ordering': ['order'], 30 | }, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /Video #6.2/films/migrations/0005_alter_film_users.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0004_auto_20211108_1854'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='film', 16 | name='users', 17 | ), 18 | migrations.AddField( 19 | model_name='film', 20 | name='users', 21 | field=models.ManyToManyField(related_name='films', through='films.UserFilms', to=settings.AUTH_USER_MODEL), 22 | ), 23 | 24 | 25 | ] 26 | -------------------------------------------------------------------------------- /Video #6.2/films/migrations/0006_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 17:00 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0005_alter_film_users'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_pics'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #6.2/films/migrations/0007_alter_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 20:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0006_film_photo'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_photos/'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #6.2/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.2/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #6.2/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | from django.db.models.functions import Lower 4 | 5 | class User(AbstractUser): 6 | pass 7 | 8 | class Film(models.Model): 9 | name = models.CharField(max_length=128, unique=True) 10 | users = models.ManyToManyField(User, related_name='films', through='UserFilms') 11 | photo = models.ImageField(upload_to='film_photos', null=True, blank=True) 12 | 13 | class Meta: 14 | ordering = [Lower('name')] 15 | 16 | class UserFilms(models.Model): 17 | user = models.ForeignKey(User, on_delete=models.CASCADE) 18 | film = models.ForeignKey(Film, on_delete=models.CASCADE) 19 | order = models.PositiveSmallIntegerField() 20 | 21 | class Meta: 22 | ordering = ['order'] -------------------------------------------------------------------------------- /Video #6.2/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {% include 'partials/navbar.html' %} 28 | 29 |
    30 | {% block content %} 31 | {% endblock %} 32 |
    33 | 34 | 50 | 51 | -------------------------------------------------------------------------------- /Video #6.2/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
    5 | 6 |
    7 |
    8 | {% include 'partials/film-list.html' %} 9 |
    10 |
    11 |
    12 | {% endblock content %} -------------------------------------------------------------------------------- /Video #6.2/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

    Welcome!

    6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #6.2/films/templates/partials/film-detail.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |

    {{ userfilm.film.name }}

    5 | 6 |

    This film is #{{ userfilm.order }} in {{ userfilm.user.username|title}}'s list

    7 | 8 | 11 |
    12 | 13 |
    14 | {% if userfilm.film.photo %} 15 | 16 | {% else %} 17 |

    No photo :(

    18 | {% endif %} 19 | 20 |
    23 | 24 | {% csrf_token %} 25 |
    26 | 27 |
    28 | 29 | 30 |
    31 |
    32 | 33 |
    -------------------------------------------------------------------------------- /Video #6.2/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #6.2/films/templates/partials/search-results.html: -------------------------------------------------------------------------------- 1 | {% if results %} 2 | 3 | {% csrf_token %} 4 |
      5 | {% for film in results %} 6 |
    • 7 | {{ film.name }} 8 | add 13 |
    • 14 | {% endfor %} 15 |
    16 | {% else %} 17 |

    No search results

    18 | {% endif %} -------------------------------------------------------------------------------- /Video #6.2/films/templates/partials/search.html: -------------------------------------------------------------------------------- 1 |
    2 | {% csrf_token %} 3 | 10 | 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /Video #6.2/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Login

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
    13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
    17 | {% endfor %} 18 | 19 | 20 |
    21 |
    22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #6.2/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Register

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 |
    12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
    16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
    25 | 26 | 27 |
    28 |
    29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #6.2/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #6.2/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film'), 17 | path('search-film/', views.search_film, name='search-film'), 18 | path('clear/', views.clear, name='clear'), 19 | path('sort/', views.sort, name='sort'), 20 | path('detail//', views.detail, name='detail'), 21 | path('film-list-partial', views.films_partial, name='film-list-partial'), 22 | path('upload-photo//', views.upload_photo, name='upload-photo'), 23 | 24 | ] 25 | 26 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #6.2/films/utils.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Max 2 | from films.models import UserFilms 3 | 4 | 5 | def get_max_order(user) -> int: 6 | existing_films = UserFilms.objects.filter(user=user) 7 | if not existing_films.exists(): 8 | return 1 9 | else: 10 | current_max = existing_films.aggregate(max_order=Max('order'))['max_order'] 11 | return current_max + 1 12 | 13 | def reorder(user): 14 | existing_films = UserFilms.objects.filter(user=user) 15 | if not existing_films.exists(): 16 | return 17 | number_of_films = existing_films.count() 18 | new_ordering = range(1, number_of_films+1) 19 | 20 | for order, user_film in zip(new_ordering, existing_films): 21 | user_film.order = order 22 | user_film.save() 23 | -------------------------------------------------------------------------------- /Video #6.2/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #6.2/htmx/__init__.py -------------------------------------------------------------------------------- /Video #6.2/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #6.2/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from django.conf import settings 4 | from django.conf.urls.static import static 5 | 6 | urlpatterns = [ 7 | path('', include('films.urls')), 8 | path('admin/', admin.site.urls), 9 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 10 | -------------------------------------------------------------------------------- /Video #6.2/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #6.2/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.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 | -------------------------------------------------------------------------------- /Video #6.2/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #6.2/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #7/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/* -------------------------------------------------------------------------------- /Video #7/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #7/films/__init__.py -------------------------------------------------------------------------------- /Video #7/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #7/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #7/films/fixtures/films.json: -------------------------------------------------------------------------------- 1 | [{"model": "films.film", "pk": 35, "fields": {"name": "Taxi Driver"}}, {"model": "films.film", "pk": 36, "fields": {"name": "Godfather"}}, {"model": "films.film", "pk": 37, "fields": {"name": "Fargo"}}, {"model": "films.film", "pk": 38, "fields": {"name": "Big Lebowski"}}, {"model": "films.film", "pk": 39, "fields": {"name": "Mulholland Drive"}}, {"model": "films.film", "pk": 40, "fields": {"name": "Goodfellas"}}, {"model": "films.film", "pk": 41, "fields": {"name": "Raging Bull"}}, {"model": "films.film", "pk": 42, "fields": {"name": "The Shining"}}, {"model": "films.film", "pk": 43, "fields": {"name": "Chinatown"}}, {"model": "films.film", "pk": 44, "fields": {"name": "A Clockwork Orange"}}, {"model": "films.film", "pk": 45, "fields": {"name": "Dr. Strangelove"}}, {"model": "films.film", "pk": 46, "fields": {"name": "Blue Velvet"}}, {"model": "films.film", "pk": 47, "fields": {"name": "No Country for Old Men"}}, {"model": "films.film", "pk": 48, "fields": {"name": "Pulp Fiction"}}, {"model": "films.film", "pk": 49, "fields": {"name": "Escape From New York"}}, {"model": "films.film", "pk": 50, "fields": {"name": "sdgjdshgsdg"}}] 2 | -------------------------------------------------------------------------------- /Video #7/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #7/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #7/films/migrations/0003_alter_film_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-06 08:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0002_film'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='name', 16 | field=models.CharField(max_length=128, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #7/films/migrations/0004_auto_20211108_1854.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import django.db.models.functions.text 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('films', '0003_alter_film_name'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelOptions( 17 | name='film', 18 | options={'ordering': [django.db.models.functions.text.Lower('name')]}, 19 | ), 20 | migrations.CreateModel( 21 | name='UserFilms', 22 | fields=[ 23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 24 | ('order', models.PositiveSmallIntegerField()), 25 | ('film', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='films.film')), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 27 | ], 28 | options={ 29 | 'ordering': ['order'], 30 | }, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /Video #7/films/migrations/0005_alter_film_users.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0004_auto_20211108_1854'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='film', 16 | name='users', 17 | ), 18 | migrations.AddField( 19 | model_name='film', 20 | name='users', 21 | field=models.ManyToManyField(related_name='films', through='films.UserFilms', to=settings.AUTH_USER_MODEL), 22 | ), 23 | 24 | 25 | ] 26 | -------------------------------------------------------------------------------- /Video #7/films/migrations/0006_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 17:00 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0005_alter_film_users'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_pics'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #7/films/migrations/0007_alter_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 20:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0006_film_photo'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_photos/'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #7/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #7/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #7/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | from django.db.models.functions import Lower 4 | 5 | class User(AbstractUser): 6 | pass 7 | 8 | class Film(models.Model): 9 | name = models.CharField(max_length=128, unique=True) 10 | users = models.ManyToManyField(User, related_name='films', through='UserFilms') 11 | photo = models.ImageField(upload_to='film_photos', null=True, blank=True) 12 | 13 | class Meta: 14 | ordering = [Lower('name')] 15 | 16 | class UserFilms(models.Model): 17 | user = models.ForeignKey(User, on_delete=models.CASCADE) 18 | film = models.ForeignKey(Film, on_delete=models.CASCADE) 19 | order = models.PositiveSmallIntegerField() 20 | 21 | class Meta: 22 | ordering = ['order'] -------------------------------------------------------------------------------- /Video #7/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {% include 'partials/navbar.html' %} 28 | 29 |
    30 | {% block content %} 31 | {% endblock %} 32 |
    33 | 34 | 50 | 51 | -------------------------------------------------------------------------------- /Video #7/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
    5 | 6 |
    7 |
    8 | {% include 'partials/film-list.html' %} 9 |
    10 |
    11 |
    12 | {% endblock content %} -------------------------------------------------------------------------------- /Video #7/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

    Welcome!

    6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #7/films/templates/partials/film-detail.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |

    {{ userfilm.film.name }}

    5 | 6 |

    This film is #{{ userfilm.order }} in {{ userfilm.user.username|title}}'s list

    7 | 8 | 11 |
    12 | 13 |
    14 | {% if userfilm.film.photo %} 15 | 16 | {% else %} 17 |

    No photo :(

    18 | {% endif %} 19 | 20 |
    23 | 24 | {% csrf_token %} 25 |
    26 | 27 |
    28 | 29 | 30 |
    31 |
    32 | 33 |
    -------------------------------------------------------------------------------- /Video #7/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #7/films/templates/partials/search-results.html: -------------------------------------------------------------------------------- 1 | {% if results %} 2 | 3 | {% csrf_token %} 4 |
      5 | {% for film in results %} 6 |
    • 7 | {{ film.name }} 8 | add 13 |
    • 14 | {% endfor %} 15 |
    16 | {% else %} 17 |

    No search results

    18 | {% endif %} -------------------------------------------------------------------------------- /Video #7/films/templates/partials/search.html: -------------------------------------------------------------------------------- 1 |
    2 | {% csrf_token %} 3 | 10 | 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /Video #7/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Login

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
    13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
    17 | {% endfor %} 18 | 19 | 20 |
    21 |
    22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #7/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Register

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 |
    12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
    16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
    25 | 26 | 27 |
    28 |
    29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #7/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #7/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film'), 17 | path('search-film/', views.search_film, name='search-film'), 18 | path('clear/', views.clear, name='clear'), 19 | path('sort/', views.sort, name='sort'), 20 | path('detail//', views.detail, name='detail'), 21 | path('film-list-partial', views.films_partial, name='film-list-partial'), 22 | path('upload-photo//', views.upload_photo, name='upload-photo'), 23 | 24 | ] 25 | 26 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #7/films/utils.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Max 2 | from films.models import UserFilms 3 | 4 | 5 | def get_max_order(user) -> int: 6 | existing_films = UserFilms.objects.filter(user=user) 7 | if not existing_films.exists(): 8 | return 1 9 | else: 10 | current_max = existing_films.aggregate(max_order=Max('order'))['max_order'] 11 | return current_max + 1 12 | 13 | def reorder(user): 14 | existing_films = UserFilms.objects.filter(user=user) 15 | if not existing_films.exists(): 16 | return 17 | number_of_films = existing_films.count() 18 | new_ordering = range(1, number_of_films+1) 19 | 20 | for order, user_film in zip(new_ordering, existing_films): 21 | user_film.order = order 22 | user_film.save() 23 | -------------------------------------------------------------------------------- /Video #7/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #7/htmx/__init__.py -------------------------------------------------------------------------------- /Video #7/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #7/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from django.conf import settings 4 | from django.conf.urls.static import static 5 | 6 | urlpatterns = [ 7 | path('', include('films.urls')), 8 | path('admin/', admin.site.urls), 9 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 10 | -------------------------------------------------------------------------------- /Video #7/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #7/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.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 | -------------------------------------------------------------------------------- /Video #7/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #7/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #8/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/* -------------------------------------------------------------------------------- /Video #8/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #8/films/__init__.py -------------------------------------------------------------------------------- /Video #8/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #8/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #8/films/fixtures/films.json: -------------------------------------------------------------------------------- 1 | [{"model": "films.film", "pk": 35, "fields": {"name": "Taxi Driver"}}, {"model": "films.film", "pk": 36, "fields": {"name": "Godfather"}}, {"model": "films.film", "pk": 37, "fields": {"name": "Fargo"}}, {"model": "films.film", "pk": 38, "fields": {"name": "Big Lebowski"}}, {"model": "films.film", "pk": 39, "fields": {"name": "Mulholland Drive"}}, {"model": "films.film", "pk": 40, "fields": {"name": "Goodfellas"}}, {"model": "films.film", "pk": 41, "fields": {"name": "Raging Bull"}}, {"model": "films.film", "pk": 42, "fields": {"name": "The Shining"}}, {"model": "films.film", "pk": 43, "fields": {"name": "Chinatown"}}, {"model": "films.film", "pk": 44, "fields": {"name": "A Clockwork Orange"}}, {"model": "films.film", "pk": 45, "fields": {"name": "Dr. Strangelove"}}, {"model": "films.film", "pk": 46, "fields": {"name": "Blue Velvet"}}, {"model": "films.film", "pk": 47, "fields": {"name": "No Country for Old Men"}}, {"model": "films.film", "pk": 48, "fields": {"name": "Pulp Fiction"}}, {"model": "films.film", "pk": 49, "fields": {"name": "Escape From New York"}}, {"model": "films.film", "pk": 50, "fields": {"name": "sdgjdshgsdg"}}] 2 | -------------------------------------------------------------------------------- /Video #8/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #8/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #8/films/migrations/0003_alter_film_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-06 08:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0002_film'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='name', 16 | field=models.CharField(max_length=128, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #8/films/migrations/0004_auto_20211108_1854.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import django.db.models.functions.text 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('films', '0003_alter_film_name'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelOptions( 17 | name='film', 18 | options={'ordering': [django.db.models.functions.text.Lower('name')]}, 19 | ), 20 | migrations.CreateModel( 21 | name='UserFilms', 22 | fields=[ 23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 24 | ('order', models.PositiveSmallIntegerField()), 25 | ('film', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='films.film')), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 27 | ], 28 | options={ 29 | 'ordering': ['order'], 30 | }, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /Video #8/films/migrations/0005_alter_film_users.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0004_auto_20211108_1854'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='film', 16 | name='users', 17 | ), 18 | migrations.AddField( 19 | model_name='film', 20 | name='users', 21 | field=models.ManyToManyField(related_name='films', through='films.UserFilms', to=settings.AUTH_USER_MODEL), 22 | ), 23 | 24 | 25 | ] 26 | -------------------------------------------------------------------------------- /Video #8/films/migrations/0006_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 17:00 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0005_alter_film_users'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_pics'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #8/films/migrations/0007_alter_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 20:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0006_film_photo'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_photos/'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #8/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #8/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #8/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | from django.db.models.functions import Lower 4 | 5 | class User(AbstractUser): 6 | pass 7 | 8 | class Film(models.Model): 9 | name = models.CharField(max_length=128, unique=True) 10 | users = models.ManyToManyField(User, related_name='films', through='UserFilms') 11 | photo = models.ImageField(upload_to='film_photos', null=True, blank=True) 12 | 13 | class Meta: 14 | ordering = [Lower('name')] 15 | 16 | class UserFilms(models.Model): 17 | user = models.ForeignKey(User, on_delete=models.CASCADE) 18 | film = models.ForeignKey(Film, on_delete=models.CASCADE) 19 | order = models.PositiveSmallIntegerField() 20 | 21 | class Meta: 22 | ordering = ['order'] -------------------------------------------------------------------------------- /Video #8/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {% include 'partials/navbar.html' %} 28 | 29 |
    30 | {% block content %} 31 | {% endblock %} 32 |
    33 | 34 | 50 | 51 | -------------------------------------------------------------------------------- /Video #8/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
    5 | 6 |
    7 |
    8 | {% include 'partials/film-list.html' %} 9 |
    10 |
    11 |
    12 | {% endblock content %} -------------------------------------------------------------------------------- /Video #8/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

    Welcome!

    6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #8/films/templates/partials/film-detail.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |

    {{ userfilm.film.name }}

    5 | 6 |

    This film is #{{ userfilm.order }} in {{ userfilm.user.username|title}}'s list

    7 | 8 | 12 |
    13 | 14 |
    15 | {% if userfilm.film.photo %} 16 | 17 | {% else %} 18 |

    No photo :(

    19 | {% endif %} 20 | 21 |
    24 | 25 | {% csrf_token %} 26 |
    27 | 28 |
    29 | 30 | 31 |
    32 |
    33 | 34 |
    -------------------------------------------------------------------------------- /Video #8/films/templates/partials/film-list-elements.html: -------------------------------------------------------------------------------- 1 | {% for film in films %} 2 | 3 | {% if forloop.last %} 4 |
    5 | {% else %} 6 |
    7 | {% endif %} 8 | 9 | 10 |
  • 11 | 14 | #{{film.order}} {{ film.film.name }} 15 | 16 | X 21 |
  • 22 |
    23 | {% endfor %} -------------------------------------------------------------------------------- /Video #8/films/templates/partials/film-list.html: -------------------------------------------------------------------------------- 1 |
    2 |

    My Films

    3 |
    4 | {% csrf_token %} 5 | 10 | 11 |
    12 |
    13 |
    14 | 15 |
    16 | 17 |
    18 | 19 | {% if messages %} 20 |
      21 | {% for message in messages %} 22 | {{ message }} 23 | {% endfor %} 24 |
    25 | {% endif %} 26 | 27 | {% if films %} 28 | 29 | {% csrf_token %} 30 |
    31 |
    Updating...
    32 | {% include 'partials/film-list-elements.html' %} 33 |
    34 | {% else %} 35 |

    You do not have any films in your list

    36 | {% endif %} 37 | 38 |
    39 | 40 |
    41 | {% include 'partials/search.html' %} 42 |
    43 |
    44 | 45 | {% if request.method == 'POST' %} 46 | 52 | {% endif %} -------------------------------------------------------------------------------- /Video #8/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #8/films/templates/partials/search-results.html: -------------------------------------------------------------------------------- 1 | {% if results %} 2 | 3 | {% csrf_token %} 4 |
      5 | {% for film in results %} 6 |
    • 7 | {{ film.name }} 8 | add 13 |
    • 14 | {% endfor %} 15 |
    16 | {% else %} 17 |

    No search results

    18 | {% endif %} -------------------------------------------------------------------------------- /Video #8/films/templates/partials/search.html: -------------------------------------------------------------------------------- 1 |
    2 | {% csrf_token %} 3 | 10 | 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /Video #8/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Login

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
    13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
    17 | {% endfor %} 18 | 19 | 20 |
    21 |
    22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #8/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Register

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 |
    12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
    16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
    25 | 26 | 27 |
    28 |
    29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #8/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #8/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film'), 17 | path('search-film/', views.search_film, name='search-film'), 18 | path('clear/', views.clear, name='clear'), 19 | path('sort/', views.sort, name='sort'), 20 | path('detail//', views.detail, name='detail'), 21 | path('film-list-partial', views.films_partial, name='film-list-partial'), 22 | path('upload-photo//', views.upload_photo, name='upload-photo'), 23 | 24 | ] 25 | 26 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #8/films/utils.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Max 2 | from films.models import UserFilms 3 | 4 | 5 | def get_max_order(user) -> int: 6 | existing_films = UserFilms.objects.filter(user=user) 7 | if not existing_films.exists(): 8 | return 1 9 | else: 10 | current_max = existing_films.aggregate(max_order=Max('order'))['max_order'] 11 | return current_max + 1 12 | 13 | def reorder(user): 14 | existing_films = UserFilms.objects.filter(user=user) 15 | if not existing_films.exists(): 16 | return 17 | number_of_films = existing_films.count() 18 | new_ordering = range(1, number_of_films+1) 19 | 20 | for order, user_film in zip(new_ordering, existing_films): 21 | user_film.order = order 22 | user_film.save() 23 | -------------------------------------------------------------------------------- /Video #8/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #8/htmx/__init__.py -------------------------------------------------------------------------------- /Video #8/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #8/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from django.conf import settings 4 | from django.conf.urls.static import static 5 | 6 | 7 | urlpatterns = [ 8 | path('', include('films.urls')), 9 | path('admin/', admin.site.urls), 10 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 11 | -------------------------------------------------------------------------------- /Video #8/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #8/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.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 | -------------------------------------------------------------------------------- /Video #8/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #8/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } -------------------------------------------------------------------------------- /Video #9/.gitignore: -------------------------------------------------------------------------------- 1 | db.sqlite3 2 | __pycache__ 3 | *.pyc 4 | notes.txt 5 | media/* -------------------------------------------------------------------------------- /Video #9/films/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #9/films/__init__.py -------------------------------------------------------------------------------- /Video #9/films/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /Video #9/films/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FilmsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'films' 7 | -------------------------------------------------------------------------------- /Video #9/films/fixtures/films.json: -------------------------------------------------------------------------------- 1 | [{"model": "films.film", "pk": 35, "fields": {"name": "Taxi Driver"}}, {"model": "films.film", "pk": 36, "fields": {"name": "Godfather"}}, {"model": "films.film", "pk": 37, "fields": {"name": "Fargo"}}, {"model": "films.film", "pk": 38, "fields": {"name": "Big Lebowski"}}, {"model": "films.film", "pk": 39, "fields": {"name": "Mulholland Drive"}}, {"model": "films.film", "pk": 40, "fields": {"name": "Goodfellas"}}, {"model": "films.film", "pk": 41, "fields": {"name": "Raging Bull"}}, {"model": "films.film", "pk": 42, "fields": {"name": "The Shining"}}, {"model": "films.film", "pk": 43, "fields": {"name": "Chinatown"}}, {"model": "films.film", "pk": 44, "fields": {"name": "A Clockwork Orange"}}, {"model": "films.film", "pk": 45, "fields": {"name": "Dr. Strangelove"}}, {"model": "films.film", "pk": 46, "fields": {"name": "Blue Velvet"}}, {"model": "films.film", "pk": 47, "fields": {"name": "No Country for Old Men"}}, {"model": "films.film", "pk": 48, "fields": {"name": "Pulp Fiction"}}, {"model": "films.film", "pk": 49, "fields": {"name": "Escape From New York"}}, {"model": "films.film", "pk": 50, "fields": {"name": "sdgjdshgsdg"}}] 2 | -------------------------------------------------------------------------------- /Video #9/films/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm 3 | from films.models import User 4 | 5 | 6 | class RegisterForm(UserCreationForm): 7 | class Meta: 8 | model = User 9 | fields = ["username", "password1", "password2"] -------------------------------------------------------------------------------- /Video #9/films/migrations/0002_film.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-01 17:57 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Film', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=128)), 19 | ('users', models.ManyToManyField(related_name='films', to=settings.AUTH_USER_MODEL)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /Video #9/films/migrations/0003_alter_film_name.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-06 08:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0002_film'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='name', 16 | field=models.CharField(max_length=128, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #9/films/migrations/0004_auto_20211108_1854.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import django.db.models.functions.text 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | ('films', '0003_alter_film_name'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelOptions( 17 | name='film', 18 | options={'ordering': [django.db.models.functions.text.Lower('name')]}, 19 | ), 20 | migrations.CreateModel( 21 | name='UserFilms', 22 | fields=[ 23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 24 | ('order', models.PositiveSmallIntegerField()), 25 | ('film', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='films.film')), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 27 | ], 28 | options={ 29 | 'ordering': ['order'], 30 | }, 31 | ), 32 | ] 33 | -------------------------------------------------------------------------------- /Video #9/films/migrations/0005_alter_film_users.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-08 18:54 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('films', '0004_auto_20211108_1854'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='film', 16 | name='users', 17 | ), 18 | migrations.AddField( 19 | model_name='film', 20 | name='users', 21 | field=models.ManyToManyField(related_name='films', through='films.UserFilms', to=settings.AUTH_USER_MODEL), 22 | ), 23 | 24 | 25 | ] 26 | -------------------------------------------------------------------------------- /Video #9/films/migrations/0006_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 17:00 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0005_alter_film_users'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_pics'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #9/films/migrations/0007_alter_film_photo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.2.8 on 2021-11-10 20:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('films', '0006_film_photo'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='film', 15 | name='photo', 16 | field=models.ImageField(blank=True, null=True, upload_to='film_photos/'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Video #9/films/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #9/films/migrations/__init__.py -------------------------------------------------------------------------------- /Video #9/films/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | from django.db.models.functions import Lower 4 | 5 | class User(AbstractUser): 6 | pass 7 | 8 | class Film(models.Model): 9 | name = models.CharField(max_length=128, unique=True) 10 | users = models.ManyToManyField(User, related_name='films', through='UserFilms') 11 | photo = models.ImageField(upload_to='film_photos', null=True, blank=True) 12 | 13 | class Meta: 14 | ordering = [Lower('name')] 15 | 16 | class UserFilms(models.Model): 17 | user = models.ForeignKey(User, on_delete=models.CASCADE) 18 | film = models.ForeignKey(Film, on_delete=models.CASCADE) 19 | order = models.PositiveSmallIntegerField() 20 | 21 | class Meta: 22 | ordering = ['order'] -------------------------------------------------------------------------------- /Video #9/films/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Movie App 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {% include 'partials/navbar.html' %} 28 | 29 |
    30 | {% block content %} 31 | {% endblock %} 32 |
    33 | 34 | 50 | 51 | -------------------------------------------------------------------------------- /Video #9/films/templates/films.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
    5 | 6 |
    7 |
    8 | {% include 'partials/film-list.html' %} 9 |
    10 |
    11 |
    12 | {% endblock content %} -------------------------------------------------------------------------------- /Video #9/films/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |

    Welcome!

    6 | 7 | {% lorem 2 p %} 8 | 9 | {% endblock content %} -------------------------------------------------------------------------------- /Video #9/films/templates/partials/film-detail.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |

    {{ userfilm.film.name }}

    5 | 6 |

    This film is #{{ userfilm.order }} in {{ userfilm.user.username|title}}'s list

    7 | 8 | 12 |
    13 | 14 |
    15 | {% if userfilm.film.photo %} 16 | 17 | {% else %} 18 |

    No photo :(

    19 | {% endif %} 20 | 21 |
    24 | 25 | {% csrf_token %} 26 |
    27 | 28 |
    29 | 30 | 31 |
    32 |
    33 | 34 |
    -------------------------------------------------------------------------------- /Video #9/films/templates/partials/film-list-elements.html: -------------------------------------------------------------------------------- 1 | {% for film in films %} 2 | 3 | {% if forloop.last %} 4 |
    5 | {% else %} 6 |
    7 | {% endif %} 8 | 9 | 10 |
  • 11 | 14 | #{{film.order}} {{ film.film.name }} 15 | 16 | X 21 |
  • 22 |
    23 | {% endfor %} -------------------------------------------------------------------------------- /Video #9/films/templates/partials/film-list.html: -------------------------------------------------------------------------------- 1 |
    2 |

    My Films

    3 |
    4 | {% csrf_token %} 5 | 10 | 11 |
    12 |
    13 |
    14 | 15 |
    16 | 17 |
    18 | 19 | {% if messages %} 20 |
      21 | {% for message in messages %} 22 | {{ message }} 23 | {% endfor %} 24 |
    25 | {% endif %} 26 | 27 | {% if films %} 28 | 29 | {% csrf_token %} 30 |
    31 |
    Updating...
    32 | {% include 'partials/film-list-elements.html' %} 33 |
    34 | {% else %} 35 |

    You do not have any films in your list

    36 | {% endif %} 37 | 38 |
    39 | 40 |
    41 | {% include 'partials/search.html' %} 42 |
    43 |
    44 | 45 | {% if request.method == 'POST' %} 46 | 52 | {% endif %} -------------------------------------------------------------------------------- /Video #9/films/templates/partials/navbar.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Video #9/films/templates/partials/search-results.html: -------------------------------------------------------------------------------- 1 | {% if results %} 2 | 3 | {% csrf_token %} 4 |
      5 | {% for film in results %} 6 |
    • 7 | {{ film.name }} 8 | add 13 |
    • 14 | {% endfor %} 15 |
    16 | {% else %} 17 |

    No search results

    18 | {% endif %} -------------------------------------------------------------------------------- /Video #9/films/templates/partials/search.html: -------------------------------------------------------------------------------- 1 |
    2 | {% csrf_token %} 3 | 10 | 11 | 12 |
    13 |
    14 | -------------------------------------------------------------------------------- /Video #9/films/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Login

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 | {% for field in form %} 12 |
    13 | 14 | {{ field.errors }} 15 | {% render_field field class="form-control" placeholder=field.name %} 16 |
    17 | {% endfor %} 18 | 19 | 20 |
    21 |
    22 | 23 | {% endblock content %} -------------------------------------------------------------------------------- /Video #9/films/templates/registration/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load widget_tweaks %} 3 | 4 | {% block content %} 5 |
    6 |

    Register

    7 |
    8 |
    9 | {% csrf_token %} 10 | 11 |
    12 | 13 | {{ form.username.errors }} 14 | {% render_field form.username class="form-control" hx-post="/check_username/" hx-swap="outerhtml" hx-trigger="keyup changed" hx-target="#username-error" %} 15 |
    16 | 17 | 18 | {{ form.password1.errors }} 19 | {% render_field form.password1 class="form-control" %} 20 | 21 | 22 | {{ form.password2.errors }} 23 | {% render_field form.password2 class="form-control" %} 24 |
    25 | 26 | 27 |
    28 |
    29 | {% endblock content %} 30 | -------------------------------------------------------------------------------- /Video #9/films/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /Video #9/films/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from films import views 3 | from django.contrib.auth.views import LogoutView 4 | 5 | urlpatterns = [ 6 | path('index/', views.IndexView.as_view(), name='index'), 7 | path('login/', views.Login.as_view(), name='login'), 8 | path('logout/', LogoutView.as_view(), name='logout'), 9 | path("register/", views.RegisterView.as_view(), name="register"), 10 | path("films/", views.FilmList.as_view(), name='film-list'), 11 | ] 12 | 13 | htmx_urlpatterns = [ 14 | path('check_username/', views.check_username, name='check-username'), 15 | path('add-film/', views.add_film, name='add-film'), 16 | path('delete-film//', views.delete_film, name='delete-film'), 17 | path('search-film/', views.search_film, name='search-film'), 18 | path('clear/', views.clear, name='clear'), 19 | path('sort/', views.sort, name='sort'), 20 | path('detail//', views.detail, name='detail'), 21 | path('film-list-partial', views.films_partial, name='film-list-partial'), 22 | path('upload-photo//', views.upload_photo, name='upload-photo'), 23 | 24 | ] 25 | 26 | urlpatterns += htmx_urlpatterns -------------------------------------------------------------------------------- /Video #9/films/utils.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Max 2 | from films.models import UserFilms 3 | 4 | 5 | def get_max_order(user) -> int: 6 | existing_films = UserFilms.objects.filter(user=user) 7 | if not existing_films.exists(): 8 | return 1 9 | else: 10 | current_max = existing_films.aggregate(max_order=Max('order'))['max_order'] 11 | return current_max + 1 12 | 13 | def reorder(user): 14 | existing_films = UserFilms.objects.filter(user=user) 15 | if not existing_films.exists(): 16 | return 17 | number_of_films = existing_films.count() 18 | new_ordering = range(1, number_of_films+1) 19 | 20 | for order, user_film in zip(new_ordering, existing_films): 21 | user_film.order = order 22 | user_film.save() 23 | -------------------------------------------------------------------------------- /Video #9/htmx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bugbytes-io/django-htmx/421cacc15ca8b6f464a249ea60b58f767f425c98/Video #9/htmx/__init__.py -------------------------------------------------------------------------------- /Video #9/htmx/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for htmx project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'htmx.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Video #9/htmx/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from django.conf import settings 4 | from django.conf.urls.static import static 5 | import debug_toolbar 6 | 7 | urlpatterns = [ 8 | path('', include('films.urls')), 9 | path('admin/', admin.site.urls), 10 | path('__debug__/', include(debug_toolbar.urls)), 11 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 12 | -------------------------------------------------------------------------------- /Video #9/htmx/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for htmx 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/3.2/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.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Video #9/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.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 | -------------------------------------------------------------------------------- /Video #9/requirements.txt: -------------------------------------------------------------------------------- 1 | Django==3.2.8 2 | django-extensions==3.1.3 3 | django-widget-tweaks==1.4.8 -------------------------------------------------------------------------------- /Video #9/static/css/styles.css: -------------------------------------------------------------------------------- 1 | #navbar { 2 | height: 100px; 3 | } 4 | 5 | .success { 6 | color: green; 7 | transition: all ease-in .5s; 8 | } 9 | 10 | .error { 11 | color: red; 12 | font-size: 50px; 13 | transform: rotate(45deg); 14 | transition: all ease-in 5s; 15 | } --------------------------------------------------------------------------------