fix: extracted all web related stuff to a new app
This commit is contained in:
@@ -40,6 +40,7 @@ PROJECT_APPS = [
|
|||||||
"theme",
|
"theme",
|
||||||
"tpv",
|
"tpv",
|
||||||
"users",
|
"users",
|
||||||
|
"web",
|
||||||
]
|
]
|
||||||
|
|
||||||
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + PROJECT_APPS
|
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + PROJECT_APPS
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ from django.contrib import admin
|
|||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", include("shop.urls")),
|
path("", include("web.urls", namespace='web')),
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("api/v1/", include("config.api.v1.urls")),
|
path("api/v1/", include("config.api.v1.urls")),
|
||||||
path("watchman/", include("watchman.urls")),
|
path("watchman/", include("watchman.urls")),
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ class TestWebComponents(TestCase, CreateProductsMixin):
|
|||||||
self.product = self.create_product()
|
self.product = self.create_product()
|
||||||
|
|
||||||
def test_list_products_component(self):
|
def test_list_products_component(self):
|
||||||
response = self.client.get(reverse("shop:list_products"))
|
response = self.client.get(reverse("web:list_products"))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ class TestIndex(TestCase, CreateProductsMixin):
|
|||||||
self.product = self.create_product()
|
self.product = self.create_product()
|
||||||
|
|
||||||
def test_index_view(self):
|
def test_index_view(self):
|
||||||
response = self.client.get(reverse("shop:index"))
|
response = self.client.get(reverse("web:index"))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
def test_product_detail_view(self):
|
def test_product_detail_view(self):
|
||||||
response = self.client.get(
|
response = self.client.get(
|
||||||
reverse(
|
reverse(
|
||||||
"shop:product_detail",
|
"web:product_detail",
|
||||||
kwargs={"pk": self.product.pk, "slug": self.product.slug},
|
kwargs={"pk": self.product.pk, "slug": self.product.slug},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-7
@@ -1,12 +1,6 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from shop.views import index, list_products, product_detail
|
|
||||||
|
|
||||||
app_name = "shop"
|
app_name = "shop"
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = []
|
||||||
path("", index, name="index"),
|
|
||||||
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
|
||||||
path("shop/components/products/", list_products, name="list_products"),
|
|
||||||
]
|
|
||||||
|
|||||||
+3
-3
@@ -7,7 +7,7 @@ from shop.models import Product
|
|||||||
|
|
||||||
|
|
||||||
class IndexView(TemplateView):
|
class IndexView(TemplateView):
|
||||||
template_name = "shop/index.html"
|
template_name = "web/index.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
return {
|
return {
|
||||||
@@ -16,7 +16,7 @@ class IndexView(TemplateView):
|
|||||||
|
|
||||||
|
|
||||||
class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
||||||
template_name = "shop/list_products.html"
|
template_name = "web/list_products.html"
|
||||||
queryset = Product.objects.all()
|
queryset = Product.objects.all()
|
||||||
filter_class = ProductFilter
|
filter_class = ProductFilter
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
|||||||
|
|
||||||
|
|
||||||
class ProductDetail(TemplateView):
|
class ProductDetail(TemplateView):
|
||||||
template_name = "shop/product_detail.html"
|
template_name = "web/product_detail.html"
|
||||||
|
|
||||||
def get_context_data(self, pk, slug, **kwargs):
|
def get_context_data(self, pk, slug, **kwargs):
|
||||||
product = get_object_or_404(Product, pk=pk)
|
product = get_object_or_404(Product, pk=pk)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class TestLogin(APITestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert response.status_code == status.HTTP_302_FOUND
|
assert response.status_code == status.HTTP_302_FOUND
|
||||||
assert response.url == reverse("shop:index")
|
assert response.url == reverse("web:index")
|
||||||
|
|
||||||
def test_login_get(self):
|
def test_login_get(self):
|
||||||
response = self.client.get(reverse("users:login"))
|
response = self.client.get(reverse("users:login"))
|
||||||
@@ -43,11 +43,11 @@ class TestLogin(APITestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert response.status_code == status.HTTP_302_FOUND
|
assert response.status_code == status.HTTP_302_FOUND
|
||||||
assert response.url == reverse("shop:index")
|
assert response.url == reverse("web:index")
|
||||||
|
|
||||||
response = self.client.get(reverse("users:login"))
|
response = self.client.get(reverse("users:login"))
|
||||||
assert response.status_code == status.HTTP_302_FOUND
|
assert response.status_code == status.HTTP_302_FOUND
|
||||||
assert response.url == reverse("shop:index")
|
assert response.url == reverse("web:index")
|
||||||
|
|
||||||
def test_login_failed(self):
|
def test_login_failed(self):
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
@@ -70,13 +70,13 @@ class TestLogin(APITestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert response.status_code == status.HTTP_302_FOUND
|
assert response.status_code == status.HTTP_302_FOUND
|
||||||
assert response.url == reverse("shop:index")
|
assert response.url == reverse("web:index")
|
||||||
|
|
||||||
response = self.client.post(reverse("users:logout"))
|
response = self.client.post(reverse("users:logout"))
|
||||||
assert response.status_code == status.HTTP_302_FOUND
|
assert response.status_code == status.HTTP_302_FOUND
|
||||||
assert response.url == reverse("shop:index")
|
assert response.url == reverse("web:index")
|
||||||
|
|
||||||
def test_logout_already_logged_out(self):
|
def test_logout_already_logged_out(self):
|
||||||
response = self.client.post(reverse("users:logout"))
|
response = self.client.post(reverse("users:logout"))
|
||||||
assert response.status_code == status.HTTP_302_FOUND
|
assert response.status_code == status.HTTP_302_FOUND
|
||||||
assert response.url == reverse("shop:index")
|
assert response.url == reverse("web:index")
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@ class RedirectionMixin:
|
|||||||
|
|
||||||
class LoginView(View, RedirectionMixin):
|
class LoginView(View, RedirectionMixin):
|
||||||
template_name = "users/login.html"
|
template_name = "users/login.html"
|
||||||
redirect_to = "shop:index"
|
redirect_to = "web:index"
|
||||||
login_form_class = LoginForm
|
login_form_class = LoginForm
|
||||||
|
|
||||||
def get_login_form(self, request):
|
def get_login_form(self, request):
|
||||||
@@ -40,7 +40,7 @@ class LoginView(View, RedirectionMixin):
|
|||||||
|
|
||||||
|
|
||||||
class LogoutView(View, RedirectionMixin):
|
class LogoutView(View, RedirectionMixin):
|
||||||
redirect_to = "shop:index"
|
redirect_to = "web:index"
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
logout_user(request)
|
logout_user(request)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class WebConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "web"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
+11
-11
@@ -7,7 +7,7 @@
|
|||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<div class="flex items-center space-x-8">
|
<div class="flex items-center space-x-8">
|
||||||
<div class="shrink-0">
|
<div class="shrink-0">
|
||||||
<a href="{% url 'shop:index' %}">
|
<a href="{% url 'web:index' %}">
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Shoppy</h1>
|
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Shoppy</h1>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -15,25 +15,25 @@
|
|||||||
<!-- Categories -->
|
<!-- Categories -->
|
||||||
<ul class="hidden lg:flex items-center justify-start gap-6 md:gap-8 py-3 sm:justify-center">
|
<ul class="hidden lg:flex items-center justify-start gap-6 md:gap-8 py-3 sm:justify-center">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" title=""
|
<a href="{% url 'web:index' %}" title=""
|
||||||
class="flex text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
class="flex text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
||||||
{% translate 'Inicio' %}
|
{% translate 'Inicio' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="shrink-0">
|
<li class="shrink-0">
|
||||||
<a href="{% url 'shop:index' %}" title=""
|
<a href="{% url 'web:index' %}" title=""
|
||||||
class="flex text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
class="flex text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
||||||
{% translate 'Más vendidos' %}
|
{% translate 'Más vendidos' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="shrink-0">
|
<li class="shrink-0">
|
||||||
<a href="{% url 'shop:index' %}" title=""
|
<a href="{% url 'web:index' %}" title=""
|
||||||
class="flex text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
class="flex text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
||||||
{% translate 'Ideas de regalo' %}
|
{% translate 'Ideas de regalo' %}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="shrink-0">
|
<li class="shrink-0">
|
||||||
<a href="{% url 'shop:index' %}" title=""
|
<a href="{% url 'web:index' %}" title=""
|
||||||
class="text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
class="text-sm font-medium text-gray-900 hover:text-primary-700 dark:text-white dark:hover:text-primary-500">
|
||||||
{% translate 'Ofertas del día' %}
|
{% translate 'Ofertas del día' %}
|
||||||
</a>
|
</a>
|
||||||
@@ -119,22 +119,22 @@
|
|||||||
class="bg-gray-50 dark:bg-gray-700 dark:border-gray-600 border border-gray-200 rounded-lg py-3 hidden px-4 mt-4">
|
class="bg-gray-50 dark:bg-gray-700 dark:border-gray-600 border border-gray-200 rounded-lg py-3 hidden px-4 mt-4">
|
||||||
<ul class="text-gray-900 dark:text-white text-sm font-medium dark:text-white space-y-3">
|
<ul class="text-gray-900 dark:text-white text-sm font-medium dark:text-white space-y-3">
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Inicio' %}</a>
|
<a href="{% url 'web:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Inicio' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Más vendidos' %}</a>
|
<a href="{% url 'web:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Más vendidos' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Ideas de regalo' %}</a>
|
<a href="{% url 'web:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Ideas de regalo' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Juegos' %}</a>
|
<a href="{% url 'web:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Juegos' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Electrónica' %}</a>
|
<a href="{% url 'web:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Electrónica' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'shop:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Ofertas del día' %}</a>
|
<a href="{% url 'web:index' %}" class="hover:text-primary-700 dark:hover:text-primary-500">{% translate 'Ofertas del día' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
<div
|
<div
|
||||||
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||||
<div class="h-56 w-full">
|
<div class="h-56 w-full">
|
||||||
<a href="{% url 'shop:product_detail' pk=product.pk slug=product.slug %}">
|
<a href="{% url 'web:product_detail' pk=product.pk slug=product.slug %}">
|
||||||
<img class="mx-auto h-full dark:hidden" src="{{ product.images.all|first }}"
|
<img class="mx-auto h-full dark:hidden" src="{{ product.images.all|first }}"
|
||||||
alt="{{ product.name }}"/>
|
alt="{{ product.name }}"/>
|
||||||
<img class="mx-auto hidden h-full dark:block" src="{{ product.images.all|first }}"
|
<img class="mx-auto hidden h-full dark:block" src="{{ product.images.all|first }}"
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pt-6">
|
<div class="pt-6">
|
||||||
|
|
||||||
<a href="{% url 'shop:product_detail' pk=product.pk slug=product.slug %}"
|
<a href="{% url 'web:product_detail' pk=product.pk slug=product.slug %}"
|
||||||
class="text-lg font-semibold leading-tight text-gray-900 hover:underline dark:text-white">{{ product.name }}</a>
|
class="text-lg font-semibold leading-tight text-gray-900 hover:underline dark:text-white">{{ product.name }}</a>
|
||||||
|
|
||||||
<div class="mt-2 flex items-center gap-2">
|
<div class="mt-2 flex items-center gap-2">
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
<div class="flex flex-col items-center justify-between p-4 space-y-3 md:flex-row md:space-y-0 md:space-x-4">
|
<div class="flex flex-col items-center justify-between p-4 space-y-3 md:flex-row md:space-y-0 md:space-x-4">
|
||||||
<div class="w-full md:w-full">
|
<div class="w-full md:w-full">
|
||||||
<form class="flex items-center"
|
<form class="flex items-center"
|
||||||
hx-get="{% url 'shop:list_products' %}"
|
hx-get="{% url 'web:list_products' %}"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
hx-trigger="keyup changed delay:500ms"
|
hx-trigger="keyup changed delay:500ms"
|
||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
{% include 'components/products/list_filters.html' %}
|
{% include 'components/products/list_filters.html' %}
|
||||||
<section
|
<section
|
||||||
class="p-8"
|
class="p-8"
|
||||||
hx-get="{% url 'shop:list_products' %}{% querystring request.GET %}"
|
hx-get="{% url 'web:list_products' %}{% querystring request.GET %}"
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4
|
hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:outline-none focus:ring-4
|
||||||
focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700
|
focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700
|
||||||
dark:hover:text-white dark:focus:ring-gray-700"
|
dark:hover:text-white dark:focus:ring-gray-700"
|
||||||
hx-get="{% url 'shop:list_products' %}{% querystring request.GET %}{% querystring page=9 %}"
|
hx-get="{% url 'web:list_products' %}{% querystring request.GET %}{% querystring page=9 %}"
|
||||||
hx-trigger="click"
|
hx-trigger="click"
|
||||||
hx-target="#products"
|
hx-target="#products"
|
||||||
hx-swap="beforeend"
|
hx-swap="beforeend"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from shop.views import index, list_products, product_detail
|
||||||
|
|
||||||
|
app_name = "web"
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", index, name="index"),
|
||||||
|
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
||||||
|
path("shop/components/products/", list_products, name="list_products"),
|
||||||
|
]
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
from shop.filters import ProductFilter
|
||||||
|
from shop.mixins import FilteredQuerysetMixin, PaginatedQuerysetMixin
|
||||||
|
from shop.models import Product
|
||||||
|
|
||||||
|
|
||||||
|
class IndexView(TemplateView):
|
||||||
|
template_name = "web/index.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
return {
|
||||||
|
"title": "Shoppy",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
||||||
|
template_name = "web/list_products.html"
|
||||||
|
queryset = Product.objects.all()
|
||||||
|
filter_class = ProductFilter
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
qs = self.get_queryset()
|
||||||
|
products = self.get_paginated_queryset(qs)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"products": products,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ProductDetail(TemplateView):
|
||||||
|
template_name = "web/product_detail.html"
|
||||||
|
|
||||||
|
def get_context_data(self, pk, slug, **kwargs):
|
||||||
|
product = get_object_or_404(Product, pk=pk)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"product": product,
|
||||||
|
"title": product.name,
|
||||||
|
"description": product.description,
|
||||||
|
"image": product.images.first(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
index = IndexView.as_view()
|
||||||
|
list_products = ListProducts.as_view()
|
||||||
|
product_detail = ProductDetail.as_view()
|
||||||
Reference in New Issue
Block a user