diff --git a/demo/demo/settings.py b/demo/demo/settings.py index a07f8561..7e2dd37e 100644 --- a/demo/demo/settings.py +++ b/demo/demo/settings.py @@ -38,6 +38,10 @@ "django.contrib.staticfiles", "core", "products", + "crispy_forms", + "crispy_tailwind", + "template_partials", + "django_htmx", ] MIDDLEWARE = [ @@ -48,6 +52,7 @@ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", + "django_htmx.middleware.HtmxMiddleware", ] ROOT_URLCONF = "demo.urls" @@ -124,5 +129,8 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" +CRISPY_ALLOWED_TEMPLATE_PACKS = "tailwind" +CRISPY_TEMPLATE_PACK = "tailwind" + SUPERUSER_EMAIL = "project@gmail.com" SUPERUSER_PASSWORD = "password" diff --git a/demo/demo/urls.py b/demo/demo/urls.py index d5b2cd9a..e7447b12 100644 --- a/demo/demo/urls.py +++ b/demo/demo/urls.py @@ -1,19 +1,3 @@ -""" -URL configuration for demo project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/4.2/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" from django.contrib import admin from django.urls import include from django.urls import path @@ -23,5 +7,5 @@ urlpatterns = [ path("admin/", admin.site.urls), path("", RedirectView.as_view(url=reverse_lazy("products:product_list"))), - path("products/", include("products.urls")), + path("products/", include("products.urls", namespace="products")), ] diff --git a/demo/products/forms.py b/demo/products/forms.py index 57193198..0266ce3d 100644 --- a/demo/products/forms.py +++ b/demo/products/forms.py @@ -6,4 +6,4 @@ class ProductForm(ModelForm): class Meta: model = Product - fields = ("id", "name", "description", "price", "slug", "sku") + fields = ("id", "name", "description", "price", "sku") diff --git a/demo/products/migrations/0002_category.py b/demo/products/migrations/0002_category.py new file mode 100644 index 00000000..d669f56a --- /dev/null +++ b/demo/products/migrations/0002_category.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0 on 2023-12-21 14:36 +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("products", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="Category", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=100)), + ("slug", models.SlugField(max_length=100, unique=True)), + ], + ), + ] diff --git a/demo/products/migrations/0003_remove_product_slug_alter_product_name.py b/demo/products/migrations/0003_remove_product_slug_alter_product_name.py new file mode 100644 index 00000000..51d949af --- /dev/null +++ b/demo/products/migrations/0003_remove_product_slug_alter_product_name.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.8 on 2023-12-21 19:46 +from django.db import migrations +from django.db import models + + +class Migration(migrations.Migration): + dependencies = [ + ("products", "0002_category"), + ] + + operations = [ + migrations.RemoveField( + model_name="product", + name="slug", + ), + migrations.AlterField( + model_name="product", + name="name", + field=models.CharField(max_length=100, unique=True), + ), + ] diff --git a/demo/products/models.py b/demo/products/models.py index 3962ddc0..f0cb827f 100644 --- a/demo/products/models.py +++ b/demo/products/models.py @@ -2,13 +2,15 @@ class Product(models.Model): - name = models.CharField(max_length=100) + name = models.CharField(max_length=100, unique=True) description = models.TextField() price = models.DecimalField(max_digits=10, decimal_places=2) - # image = models.ImageField(upload_to="products/", null=True, blank=True) - slug = models.SlugField(max_length=100, unique=True) sku = models.CharField(max_length=100, unique=True) + @property + def slug(self): + return self.name.lower().replace(" ", "-") + class Category(models.Model): name = models.CharField(max_length=100) diff --git a/demo/products/urls.py b/demo/products/urls.py index baa4a089..685e4bb3 100644 --- a/demo/products/urls.py +++ b/demo/products/urls.py @@ -2,6 +2,7 @@ from . import views + app_name = "products" urlpatterns = [ diff --git a/demo/products/views.py b/demo/products/views.py index 38cd351b..b7905b6a 100644 --- a/demo/products/views.py +++ b/demo/products/views.py @@ -12,10 +12,11 @@ def product_list(request: HttpRequest): products = Product.objects.all() + template_name = "products/product_list.html#table" if request.htmx else "products/product_list.html" return TemplateResponse( request, - "products/product_list.html", - context={"products": paginate_queryset(request, products)}, + template_name, + context={"products": paginate_queryset(request, products, 2)}, ) diff --git a/demo/requirements.txt b/demo/requirements.txt new file mode 100644 index 00000000..3d6a3418 --- /dev/null +++ b/demo/requirements.txt @@ -0,0 +1,5 @@ +django +django-crispy-forms +crispy-tailwind +django-template-partials +django-htmx diff --git a/demo/templates/base.html b/demo/templates/base.html index 5ac56dbc..65da9861 100644 --- a/demo/templates/base.html +++ b/demo/templates/base.html @@ -1,15 +1,18 @@ - - - - My Website - - - -
- {% block content %} - {% endblock %} -
- + + + + My Website + + + + +
+
+ {% block content %} + {% endblock content %} +
+
+ diff --git a/demo/templates/products/product_create.html b/demo/templates/products/product_create.html index e69de29b..6da2e6ea 100644 --- a/demo/templates/products/product_create.html +++ b/demo/templates/products/product_create.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} +{% load crispy_forms_tags %} + +{% block content %} +

Create Product

+ +
+ {% csrf_token %} + {{form|crispy}} + + +
+{% endblock content %} diff --git a/demo/templates/products/product_detail.html b/demo/templates/products/product_detail.html index e69de29b..1db1238d 100644 --- a/demo/templates/products/product_detail.html +++ b/demo/templates/products/product_detail.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block content %} + +
+

Product - {{ product }}

+ + + All Products + +
+ + + + + + Edit + + + +{% endblock content %} diff --git a/demo/templates/products/product_list.html b/demo/templates/products/product_list.html index 021dd3ea..5c153166 100644 --- a/demo/templates/products/product_list.html +++ b/demo/templates/products/product_list.html @@ -1,30 +1,122 @@ {% extends 'base.html' %} +{% load partials %} + {% block content %} - - - - - - - - - {% for product in products %} - - - - - {% endfor %} - -
Product NamePrice
{{ product.name }}{{ product.price }}
- -