feat: register page
This commit is contained in:
@@ -5,7 +5,7 @@ from django.utils.text import gettext_lazy as _
|
|||||||
|
|
||||||
class LoginForm(AuthenticationForm):
|
class LoginForm(AuthenticationForm):
|
||||||
username = UsernameField(
|
username = UsernameField(
|
||||||
widget=forms.TextInput(
|
widget=forms.EmailInput(
|
||||||
attrs={
|
attrs={
|
||||||
"autofocus": True,
|
"autofocus": True,
|
||||||
"class": "my-2 bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 "
|
"class": "my-2 bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 "
|
||||||
@@ -20,9 +20,10 @@ class LoginForm(AuthenticationForm):
|
|||||||
widget=forms.PasswordInput(
|
widget=forms.PasswordInput(
|
||||||
attrs={
|
attrs={
|
||||||
"autocomplete": "current-password",
|
"autocomplete": "current-password",
|
||||||
"class": "my-2 bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 "
|
"class": "my-2 bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg "
|
||||||
"focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 "
|
"focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 "
|
||||||
"dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
|
"dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 "
|
||||||
|
"dark:focus:border-primary-500",
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
from django import forms
|
||||||
|
from django.contrib.auth.forms import SetPasswordMixin, BaseUserCreationForm
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.forms import EmailField
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterForm(BaseUserCreationForm, SetPasswordMixin):
|
||||||
|
password1, password2 = SetPasswordMixin.create_password_fields()
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
for field_name in self.fields.keys():
|
||||||
|
self.fields[field_name].widget.attrs.update(
|
||||||
|
{
|
||||||
|
"class": "my-2 bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg "
|
||||||
|
"focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 "
|
||||||
|
"dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 "
|
||||||
|
"dark:focus:border-primary-500"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = (
|
||||||
|
"email",
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
)
|
||||||
|
field_classes = {
|
||||||
|
"email": EmailField,
|
||||||
|
"first_name": forms.CharField,
|
||||||
|
"last_name": forms.CharField,
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
</label>
|
</label>
|
||||||
{{ field }}
|
{{ field }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -44,7 +43,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<p class="text-sm font-light text-gray-500 mt-4 dark:text-gray-400">
|
<p class="text-sm font-light text-gray-500 mt-4 dark:text-gray-400">
|
||||||
{% translate '¿Aún no tienes cuenta?' %}
|
{% translate '¿Aún no tienes cuenta?' %}
|
||||||
<a href="#" class="font-medium text-primary-600 hover:underline dark:text-primary-500">{% translate 'Regístrate aquí' %}</a>
|
<a href="{% url 'web:register' %}" class="font-medium text-primary-600 hover:underline dark:text-primary-500">{% translate 'Regístrate aquí' %}</a>
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,45 +1,54 @@
|
|||||||
{% extends 'base/base.html' %}
|
{% extends 'theme/base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
{% block content %}
|
{% block main %}
|
||||||
<section class="bg-gray-50 dark:bg-gray-900">
|
<section class="bg-gray-50 dark:bg-gray-900">
|
||||||
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
|
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
|
||||||
<a href="#" class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
|
|
||||||
<img class="w-8 h-8 mr-2" src="https://flowbite.s3.amazonaws.com/blocks/marketing-ui/logo.svg" alt="logo">
|
<a href="{% url 'web:index' %}" class="flex items-center mb-6 text-2xl font-semibold text-gray-900 dark:text-white">
|
||||||
Flowbite
|
<img class="w-8 h-8 mr-2" src="{{ logo }}" alt="logo">
|
||||||
|
{{ title }}
|
||||||
</a>
|
</a>
|
||||||
<div class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
|
|
||||||
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
<div
|
||||||
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
|
class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
|
||||||
Create and account
|
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
||||||
</h1>
|
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
|
||||||
<form class="space-y-4 md:space-y-6" action="#">
|
{% translate 'Crea tu cuenta' %}
|
||||||
<div>
|
</h1>
|
||||||
<label for="email" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your email</label>
|
<form action="{% url 'web:register' %}" method="post">
|
||||||
<input type="email" name="email" id="email" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-blue-500" placeholder="name@company.com" required="">
|
{% csrf_token %}
|
||||||
</div>
|
{% for field in form %}
|
||||||
<div>
|
<div class="my-2">
|
||||||
<label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
|
<label for="{{ field.id_for_label }}"
|
||||||
<input type="password" name="password" id="password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-blue-500" required="">
|
class="inline-block text-sm font-medium text-gray-900 dark:text-white mr-2">
|
||||||
</div>
|
{{ field.label }}
|
||||||
<div>
|
</label>
|
||||||
<label for="confirm-password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Confirm password</label>
|
|
||||||
<input type="confirm-password" name="confirm-password" id="confirm-password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-blue-500" required="">
|
{{ field }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-start">
|
|
||||||
<div class="flex items-center h-5">
|
{% endfor %}
|
||||||
<input id="terms" aria-describedby="terms" type="checkbox" class="w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-primary-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-primary-600 dark:ring-offset-gray-800" required="">
|
|
||||||
</div>
|
{% if errors %}
|
||||||
<div class="ml-3 text-sm">
|
{% for error in errors %}
|
||||||
<label for="terms" class="font-light text-gray-500 dark:text-gray-300">I accept the <a class="font-medium text-primary-600 hover:underline dark:text-primary-500" href="#">Terms and Conditions</a></label>
|
<span class="inline-block text-sm font-medium text-red-900 dark:text-red-400 mr-2">{{ error }}</span>
|
||||||
</div>
|
{% endfor %}
|
||||||
</div>
|
{% endif %}
|
||||||
<button type="submit" class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Create an account</button>
|
|
||||||
<p class="text-sm font-light text-gray-500 dark:text-gray-400">
|
<button class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none
|
||||||
Already have an account? <a href="#" class="font-medium text-primary-600 hover:underline dark:text-primary-500">Login here</a>
|
focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center
|
||||||
</p>
|
dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800 mt-4">
|
||||||
</form>
|
{% translate 'Crear cuenta' %}
|
||||||
</div>
|
</button>
|
||||||
|
<p class="text-sm font-light text-gray-500 mt-4 dark:text-gray-400">
|
||||||
|
{% translate '¿Ya tienes cuenta?' %}
|
||||||
|
<a href="{% url 'web:login' %}" class="font-medium text-primary-600 hover:underline dark:text-primary-500">{% translate 'Inicia sesión aquí' %}</a>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.shortcuts import reverse
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class TestRegister(TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.password = "theonering"
|
||||||
|
self.email = "sauron@mordor.middleearth"
|
||||||
|
self.first_name = "Sauron"
|
||||||
|
self.last_name = "The Lord of the Rings"
|
||||||
|
|
||||||
|
def test_create_user_account(self):
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("web:register"),
|
||||||
|
{
|
||||||
|
"email": self.email,
|
||||||
|
"password1": self.password,
|
||||||
|
"password2": self.password,
|
||||||
|
"first_name": self.first_name,
|
||||||
|
"last_name": self.last_name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
user = User.objects.filter(
|
||||||
|
username=self.email,
|
||||||
|
email=self.email,
|
||||||
|
first_name=self.first_name,
|
||||||
|
last_name=self.last_name,
|
||||||
|
).first()
|
||||||
|
|
||||||
|
assert user is not None
|
||||||
|
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.url == reverse("web:index")
|
||||||
|
|
||||||
|
def test_create_user_account_distinct_password(self):
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("web:register"),
|
||||||
|
{
|
||||||
|
"email": self.email,
|
||||||
|
"password1": self.password,
|
||||||
|
"password2": "otherpassword",
|
||||||
|
"first_name": self.first_name,
|
||||||
|
"last_name": self.last_name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not User.objects.filter(
|
||||||
|
username=self.email,
|
||||||
|
email=self.email,
|
||||||
|
first_name=self.first_name,
|
||||||
|
last_name=self.last_name,
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
def test_create_user_account_no_first_name(self):
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("web:register"),
|
||||||
|
{
|
||||||
|
"email": self.email,
|
||||||
|
"password1": self.password,
|
||||||
|
"password2": "otherpassword",
|
||||||
|
"first_name": "",
|
||||||
|
"last_name": self.last_name,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not User.objects.filter(
|
||||||
|
username=self.email,
|
||||||
|
email=self.email,
|
||||||
|
first_name="",
|
||||||
|
last_name=self.last_name,
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
assert response.status_code == 400
|
||||||
|
|
||||||
|
def test_create_user_account_no_last_name(self):
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("web:register"),
|
||||||
|
{
|
||||||
|
"email": self.email,
|
||||||
|
"password1": self.password,
|
||||||
|
"password2": "otherpassword",
|
||||||
|
"first_name": self.first_name,
|
||||||
|
"last_name": "",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert not User.objects.filter(
|
||||||
|
username=self.email,
|
||||||
|
email=self.email,
|
||||||
|
first_name=self.first_name,
|
||||||
|
last_name="",
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
assert response.status_code == 400
|
||||||
+55
-6
@@ -1,14 +1,19 @@
|
|||||||
from django.contrib.auth import login as login_user
|
from django.contrib.auth import login as login_user, authenticate
|
||||||
from django.contrib.auth import logout as logout_user
|
from django.contrib.auth import logout as logout_user
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db import IntegrityError
|
||||||
from django.shortcuts import redirect, render, reverse
|
from django.shortcuts import redirect, render, reverse
|
||||||
from django.utils.text import gettext_lazy as _
|
from django.utils.text import gettext_lazy as _
|
||||||
from django.views.generic import TemplateView, View
|
from django.views.generic import TemplateView, View
|
||||||
|
|
||||||
from shop.models import CustomerAddress
|
from shop.models import CustomerAddress
|
||||||
from users.forms import LoginForm
|
from users.forms import LoginForm, RegisterForm
|
||||||
from web.models import WebSettings
|
from web.models import WebSettings
|
||||||
|
|
||||||
|
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class RedirectionMixin:
|
class RedirectionMixin:
|
||||||
redirect_to = ""
|
redirect_to = ""
|
||||||
|
|
||||||
@@ -55,6 +60,54 @@ class LoginView(View, RedirectionMixin):
|
|||||||
return render(request, self.template_name, {"form": login_form}, status=400)
|
return render(request, self.template_name, {"form": login_form}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterView(TemplateView, RedirectionMixin):
|
||||||
|
template_name = "users/register.html"
|
||||||
|
redirect_to = "web:index"
|
||||||
|
form_class = RegisterForm
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
settings = WebSettings.load()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"form": self.form_class(),
|
||||||
|
"title": settings.web_title,
|
||||||
|
"description": _("crear cuenta"),
|
||||||
|
}
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
settings = WebSettings.load()
|
||||||
|
form = self.form_class(request.POST)
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
if form.is_valid():
|
||||||
|
user = form.save()
|
||||||
|
|
||||||
|
user.username = user.email
|
||||||
|
user.first_name = form.cleaned_data.get("first_name")
|
||||||
|
user.last_name = form.cleaned_data.get("last_name")
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
login(request, user)
|
||||||
|
return redirect(self.get_redirection())
|
||||||
|
else:
|
||||||
|
errors = form.errors
|
||||||
|
except IntegrityError as e:
|
||||||
|
errors = [_("Ya existe un usuario con ese correo electrónico"), ]
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
self.template_name,
|
||||||
|
{
|
||||||
|
"form": form,
|
||||||
|
"title": settings.web_title,
|
||||||
|
"description": _("Crear cuenta"),
|
||||||
|
"errors": errors,
|
||||||
|
},
|
||||||
|
status=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(View, RedirectionMixin):
|
class LogoutView(View, RedirectionMixin):
|
||||||
redirect_to = "web:index"
|
redirect_to = "web:index"
|
||||||
|
|
||||||
@@ -67,10 +120,6 @@ class LogoutView(View, RedirectionMixin):
|
|||||||
return redirect(self.get_redirection())
|
return redirect(self.get_redirection())
|
||||||
|
|
||||||
|
|
||||||
class RegisterView(TemplateView):
|
|
||||||
template_name = "web/register.html"
|
|
||||||
|
|
||||||
|
|
||||||
class ResetPasswordView(TemplateView):
|
class ResetPasswordView(TemplateView):
|
||||||
template_name = "web/reset-password.html"
|
template_name = "web/reset-password.html"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user