feat: moved users views to web app
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
from django.db import models
|
||||
|
||||
|
||||
class SingletonModel(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.pk = 1
|
||||
super(SingletonModel, self).save(*args, **kwargs)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
obj, created = cls.objects.get_or_create(pk=1)
|
||||
return obj
|
||||
+1
-8
@@ -1,13 +1,6 @@
|
||||
from django.urls import path
|
||||
|
||||
from users.views import login, logout, register, reset_password
|
||||
|
||||
app_name = "users"
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("login/", login, name="login"),
|
||||
path("logout/", logout, name="logout"),
|
||||
path("register/", register, name="register"),
|
||||
path("reset-password/", reset_password, name="reset-password"),
|
||||
]
|
||||
urlpatterns = []
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
from django.contrib.auth import login as login_user
|
||||
from django.contrib.auth import logout as logout_user
|
||||
from django.shortcuts import redirect, render, reverse
|
||||
from django.views.generic import TemplateView, View
|
||||
|
||||
from users.forms import LoginForm
|
||||
|
||||
|
||||
class RedirectionMixin:
|
||||
redirect_to = ""
|
||||
|
||||
def get_redirection(self):
|
||||
return reverse(self.redirect_to)
|
||||
|
||||
|
||||
class LoginView(View, RedirectionMixin):
|
||||
template_name = "users/login.html"
|
||||
redirect_to = "web:index"
|
||||
login_form_class = LoginForm
|
||||
|
||||
def get_login_form(self, request):
|
||||
return self.login_form_class(data=request.POST)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
login_form = self.login_form_class()
|
||||
return render(request, self.template_name, {"form": login_form})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
login_form = self.get_login_form(request)
|
||||
|
||||
if login_form.is_valid():
|
||||
login_user(request, login_form.get_user())
|
||||
|
||||
if not login_form.cleaned_data.get('remember_me'):
|
||||
request.session.set_expiry(0)
|
||||
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
return render(request, self.template_name, {"form": login_form}, status=400)
|
||||
|
||||
|
||||
class LogoutView(View, RedirectionMixin):
|
||||
redirect_to = "web:index"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
logout_user(request)
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
logout_user(request)
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
|
||||
class RegisterView(TemplateView):
|
||||
template_name = "users/register.html"
|
||||
|
||||
|
||||
class ResetPasswordView(TemplateView):
|
||||
template_name = "users/reset-password.html"
|
||||
|
||||
|
||||
login = LoginView.as_view()
|
||||
logout = LogoutView.as_view()
|
||||
register = RegisterView.as_view()
|
||||
reset_password = ResetPasswordView.as_view()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import TemplateView
|
||||
from shop.filters import ProductFilter
|
||||
from shop.models import Product, Cart
|
||||
from shop.models import Product, Cart, ProductPrice
|
||||
from web.mixins import FilteredQuerysetMixin, PaginatedQuerysetMixin
|
||||
from web.settings import ANONYMOUS_CART_ID_COOKIE_NAME
|
||||
from web.utils import get_or_create_cart
|
||||
@@ -9,7 +9,7 @@ from web.utils import get_or_create_cart
|
||||
|
||||
class ListProducts(TemplateView, FilteredQuerysetMixin, PaginatedQuerysetMixin):
|
||||
template_name = "web/list_products.html"
|
||||
queryset = Product.objects.all()
|
||||
queryset = Product.objects.all().prefetch_related('images', )
|
||||
filter_class = ProductFilter
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
<!-- Cart -->
|
||||
<div id="myCartDropdown1"
|
||||
class="absolute top-10 hidden z-10 mx-auto max-w-sm space-y-4 overflow-hidden rounded-lg bg-white p-4 antialiased shadow-lg dark:bg-gray-800">
|
||||
|
||||
class="absolute top-10 z-10 mx-auto max-w-sm space-y-4 overflow-hidden rounded-lg bg-white p-4 antialiased shadow-lg dark:bg-gray-800 hidden"
|
||||
>
|
||||
<div>
|
||||
{% if cart.items.count == 0 %}
|
||||
<h2 class="text-sm font-medium text-gray-900 dark:text-white">No hay nada en el carrito</h2>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
{% include 'components/users/user_dropdown.html' %}
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{% url 'users:login' %}"
|
||||
<a href="{% url 'web:login' %}"
|
||||
class="inline-flex items-center rounded-lg justify-center p-2 hover:bg-gray-100 dark:hover:bg-gray-700 text-sm font-medium leading-none text-gray-900 dark:text-white">Inicia
|
||||
sesión</a>
|
||||
{% endif %}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</ul>
|
||||
|
||||
<div class="p-2 text-sm font-medium text-gray-900 dark:text-white">
|
||||
<a href="{% url 'users:logout' %}" title=""
|
||||
<a href="{% url 'web:logout' %}" title=""
|
||||
class="inline-flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm hover:bg-gray-100 dark:hover:bg-gray-600">
|
||||
{% translate 'Cerrar sesión' %}
|
||||
</a>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
|
||||
Sign in to your account
|
||||
</h1>
|
||||
<form class="space-y-4 md:space-y-6" action="{% url 'users:login' %}" method="post">
|
||||
<form class="space-y-4 md:space-y-6" action="{% url 'web:login' %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% for field in form %}
|
||||
<label for="{{ field.id_for_label }}"
|
||||
@@ -14,13 +14,13 @@
|
||||
<img class="w-full hidden dark:block" src="{{ product.images.all|first }}" alt=""/>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 sm:mt-8 lg:mt-0">
|
||||
<div class="my-4 sm:m-8 lg:m-0">
|
||||
<h1
|
||||
class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white"
|
||||
>
|
||||
{{ product.name }}
|
||||
</h1>
|
||||
<div class="mt-4 sm:items-center sm:gap-4 sm:flex">
|
||||
<div class="my-4 sm:items-center sm:gap-4 sm:flex">
|
||||
<p
|
||||
class="text-2xl font-extrabold text-gray-900 sm:text-3xl dark:text-white"
|
||||
>
|
||||
@@ -109,7 +109,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 sm:gap-4 sm:items-center sm:flex sm:mt-8">
|
||||
<div class="my-4 sm:gap-4 sm:items-center sm:flex sm:m-8">
|
||||
<a
|
||||
href="#"
|
||||
title=""
|
||||
@@ -136,41 +136,15 @@
|
||||
{% translate 'Añadir a lista de deseados' %}
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="#"
|
||||
title=""
|
||||
class="text-white mt-4 sm:mt-0 bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-primary-600 dark:hover:bg-primary-700 focus:outline-none dark:focus:ring-primary-800 flex items-center justify-center"
|
||||
role="button"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5 -ms-2 me-2"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 4h1.5L8 16m0 0h8m-8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm8 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4Zm.75-3H7.5M11 7H6.312M17 4v6m-3-3h6"
|
||||
/>
|
||||
</svg>
|
||||
{% include 'components/cart/add_to_cart.html' %}
|
||||
|
||||
<hr class="my-6 md:my-8 border-gray-200 dark:border-gray-800"/>
|
||||
|
||||
{% translate 'Añadir al carrito' %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<hr class="my-6 md:my-8 border-gray-200 dark:border-gray-800"/>
|
||||
|
||||
<p class="mb-6 text-gray-500 dark:text-gray-400">
|
||||
{{ product.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
@@ -19,7 +19,7 @@ class TestLogin(APITestCase):
|
||||
|
||||
def test_login(self):
|
||||
response = self.client.post(
|
||||
reverse("users:login"),
|
||||
reverse("web:login"),
|
||||
{
|
||||
"username": self.user.username,
|
||||
"password": self.password,
|
||||
@@ -30,12 +30,12 @@ class TestLogin(APITestCase):
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
def test_login_get(self):
|
||||
response = self.client.get(reverse("users:login"))
|
||||
response = self.client.get(reverse("web:login"))
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
def test_login_already_logged_in(self):
|
||||
response = self.client.post(
|
||||
reverse("users:login"),
|
||||
reverse("web:login"),
|
||||
{
|
||||
"username": self.user.username,
|
||||
"password": self.password,
|
||||
@@ -45,13 +45,13 @@ class TestLogin(APITestCase):
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
response = self.client.get(reverse("users:login"))
|
||||
response = self.client.get(reverse("web:login"))
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
def test_login_failed(self):
|
||||
response = self.client.post(
|
||||
reverse("users:login"),
|
||||
reverse("web:login"),
|
||||
{
|
||||
"username": self.user.username,
|
||||
"password": "wrongpassword",
|
||||
@@ -62,7 +62,7 @@ class TestLogin(APITestCase):
|
||||
|
||||
def test_login_then_logout(self):
|
||||
response = self.client.post(
|
||||
reverse("users:login"),
|
||||
reverse("web:login"),
|
||||
{
|
||||
"username": self.user.username,
|
||||
"password": self.password,
|
||||
@@ -72,18 +72,18 @@ class TestLogin(APITestCase):
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
response = self.client.post(reverse("users:logout"))
|
||||
response = self.client.post(reverse("web:logout"))
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
def test_logout_already_logged_out(self):
|
||||
response = self.client.post(reverse("users:logout"))
|
||||
response = self.client.post(reverse("web:logout"))
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
def test_login_then_get_logout(self):
|
||||
response = self.client.post(
|
||||
reverse("users:login"),
|
||||
reverse("web:login"),
|
||||
{
|
||||
"username": self.user.username,
|
||||
"password": self.password,
|
||||
@@ -93,6 +93,6 @@ class TestLogin(APITestCase):
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
|
||||
response = self.client.get(reverse("users:logout"))
|
||||
response = self.client.get(reverse("web:logout"))
|
||||
assert response.status_code == status.HTTP_302_FOUND
|
||||
assert response.url == reverse("web:index")
|
||||
+9
-1
@@ -1,6 +1,6 @@
|
||||
from django.urls import path
|
||||
|
||||
from web.views import index, product_detail, add_cart_item, delete_cart_item
|
||||
from web.views import index, product_detail, add_cart_item, delete_cart_item, login, logout, register, reset_password
|
||||
from web.components.views import list_products, cart_dropdown
|
||||
|
||||
app_name = "web"
|
||||
@@ -9,9 +9,17 @@ app_name = "web"
|
||||
urlpatterns = [
|
||||
path("", index, name="index"),
|
||||
path("products/<int:pk>/<str:slug>/", product_detail, name="product_detail"),
|
||||
|
||||
# users
|
||||
path("login/", login, name="login"),
|
||||
path("logout/", logout, name="logout"),
|
||||
path("register/", register, name="register"),
|
||||
path("reset-password/", reset_password, name="reset-password"),
|
||||
|
||||
# components
|
||||
path("web/components/products/", list_products, name="list_products"),
|
||||
path("web/components/cart-dropdown/", cart_dropdown, name="cart_dropdown"),
|
||||
|
||||
# api
|
||||
path("web/add-cart-item/", add_cart_item, name="add_cart_item"),
|
||||
path("web/delete-cart-item/<int:pk>/", delete_cart_item, name="delete_cart_item"),
|
||||
|
||||
+70
-2
@@ -1,13 +1,76 @@
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views.generic import TemplateView
|
||||
from django.http.response import HttpResponse
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from shop.models import Product, Cart, CartItem
|
||||
from shop.models import Product, CartItem
|
||||
from web.utils import get_or_create_cart
|
||||
from web.settings import ANONYMOUS_CART_ID_COOKIE_NAME
|
||||
|
||||
|
||||
from django.contrib.auth import login as login_user
|
||||
from django.contrib.auth import logout as logout_user
|
||||
from django.shortcuts import redirect, render, reverse
|
||||
from django.views.generic import TemplateView, View
|
||||
|
||||
from users.forms import LoginForm
|
||||
|
||||
|
||||
class RedirectionMixin:
|
||||
redirect_to = ""
|
||||
|
||||
def get_redirection(self):
|
||||
return reverse(self.redirect_to)
|
||||
|
||||
|
||||
class LoginView(View, RedirectionMixin):
|
||||
template_name = "users/login.html"
|
||||
redirect_to = "web:index"
|
||||
login_form_class = LoginForm
|
||||
|
||||
def get_login_form(self, request):
|
||||
return self.login_form_class(data=request.POST)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
login_form = self.login_form_class()
|
||||
return render(request, self.template_name, {"form": login_form})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
login_form = self.get_login_form(request)
|
||||
|
||||
if login_form.is_valid():
|
||||
login_user(request, login_form.get_user())
|
||||
|
||||
if not login_form.cleaned_data.get('remember_me'):
|
||||
request.session.set_expiry(0)
|
||||
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
return render(request, self.template_name, {"form": login_form}, status=400)
|
||||
|
||||
|
||||
class LogoutView(View, RedirectionMixin):
|
||||
redirect_to = "web:index"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
logout_user(request)
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
logout_user(request)
|
||||
return redirect(self.get_redirection())
|
||||
|
||||
|
||||
class RegisterView(TemplateView):
|
||||
template_name = "web/register.html"
|
||||
|
||||
|
||||
class ResetPasswordView(TemplateView):
|
||||
template_name = "web/reset-password.html"
|
||||
|
||||
|
||||
class IndexView(TemplateView):
|
||||
template_name = "web/index.html"
|
||||
|
||||
@@ -76,3 +139,8 @@ def delete_cart_item(request, pk, *args, **kwargs):
|
||||
|
||||
index = IndexView.as_view()
|
||||
product_detail = ProductDetail.as_view()
|
||||
|
||||
login = LoginView.as_view()
|
||||
logout = LogoutView.as_view()
|
||||
register = RegisterView.as_view()
|
||||
reset_password = ResetPasswordView.as_view()
|
||||
|
||||
Reference in New Issue
Block a user