Create registration, login and profile forms

This commit is contained in:
Ivan Kaziev 2024-04-16 17:04:12 +03:00
parent bd89672f89
commit 6ea3b78449
16 changed files with 426 additions and 9 deletions

View File

@ -109,6 +109,10 @@ USE_TZ = True
STATIC_URL = 'static/' STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_URL = "/media/" MEDIA_URL = "/media/"

View File

@ -7,6 +7,9 @@ from django.urls import include, path
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('films/', include('films.urls'), name='films'), path('films/', include('films.urls'), name='films'),
path("auth/", include("users.urls"), name="auth"),
path("auth/", include("django.contrib.auth.urls"), name="auth"),
] ]
if settings.DEBUG: if settings.DEBUG:

View File

@ -1,9 +1,9 @@
from django.urls import path from django.urls import path
from films import views from films.views import films_list, film_details
app_name = 'films' app_name = 'films'
urlpatterns = [ urlpatterns = [
path('', views.films_list, name='main'), path('', films_list, name='main'),
path('<int:film_id>/', views.film_details, name='film_details') path('<int:film_id>/', film_details, name='film_details')
] ]

View File

@ -6,11 +6,10 @@ from films.models import Film
def films_list(request: HttpResponse) -> HttpResponse: def films_list(request: HttpResponse) -> HttpResponse:
films = Film.objects.released() films = Film.objects.released()
context = {'films': films}
return render( return render(
request, request,
'films/films_list.html', 'films/films_list.html',
context, {'films': films},
) )
@ -21,7 +20,7 @@ def film_details(request: HttpResponse, film_id: int) -> HttpResponse:
) )
return render( return render(
request, request,
"catalog/film_details.html", 'films/film_details.html',
{"item": item}, {'item': item},
) )

6
CineSync/static/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% endblock title %}</title>
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'img/apple-touch-icon.png' %}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'img/favicon-32x32.png' %}">
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'img/favicon-16x16.png' %}">
<link rel="manifest" href="{% static 'img/site.webmanifest' %}">
<link rel="icon" type="image/x-icon" href="{% static 'img/favicon.ico' %}">
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/includes/header.css' %}"/>
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
</head>
<body>
{% include "includes/header.html" %}
<main class="pt-5 my-5">
<div class="container">
{% block content %} Ачё {% endblock %}
</div>
</main>
{% include "includes/footer.html" %}
<script defer src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>

View File

@ -0,0 +1,32 @@
{% extends "base.html" %}
{% load static %}
{% load i18n %}
{% block title %}
{% trans "Вход" %}
{% endblock title %}
{% block content %}
<h1>Вход в аккаунт</h1>
{% include "includes/form.html" with form=form %}
{% comment %}
{% if echo %}
<form method="post" action="{% url 'homepage:echo_submit' %}">
{% else %}
<form method="post">
{% endif %}
{% csrf_token %}
{% for field in form.visible_fields %}
<div class="mb-3 {% if field.widget_type == 'checkbox' %}form-check{% endif %}">
<label for="{{ field.id_for_label }}" class="form-label">{{ field.label }}</label>
{{ field }}
{% if field.help_text %}
<div class="form-text">{{ field.help_text }}</div>
{% endif %}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary" style="margin-top: 50px">Отправить</button>
</form>
{% endcomment %}
<br>
<a href="{% url 'users:password_reset' %}" class="link-primary link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover">Восстановить пароль</a>
<a href="{% url 'users:signup' %}" class="link-primary link-offset-2 link-underline-opacity-25 link-underline-opacity-100-hover">Создать аккаунт</a>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ user.username }}: изменить профиль{% endblock %}
{% block content %}
<h1>{{ user.username }}</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{% if user_form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
<div>{{ error }}</div>
{% endfor %}
</div>
{% endif %}
{% for field in user_form %}
<div class="mb-3">
<label for="fieldInput" class="form-label">{{ field.label }}</label>
<p id="fieldInput" aria-describedby="help">{{ field }}</p>
{% for error in field.errors %}
<div class="invalid-feedback d-block">
{{ error }}
</div>
{% endfor %}
<div id="help" class="form-text">{{ field.help_text }}</div>
</div>
{% endfor %}
{% for field in profile_form %}
<div class="mb-3">
<label for="fieldInput" class="form-label">{{ field.label }}</label>
<p id="fieldInput" aria-describedby="help">{{ field }}</p>
{% for error in field.errors %}
<div class="invalid-feedback d-block">
{{ error }}
</div>
{% endfor %}
<div id="help" class="form-text">{{ field.help_text }}</div>
</div>
{% endfor %}
{% if messages %}
{% for message in messages %}
<p> {{ message }} </p>
{% endfor %}
{% endif %}
<button class="btn btn-primary" type="submit">Сохранить изменения</button>
</form>
<a class="btn btn-primary" type="submit" href="{% url 'users:logout' %}">Выйти</a>
<a href="{% url "users:password_change" %}">Сменить пароль</a>
{% endblock content %}

View File

@ -0,0 +1,5 @@
{% extends "base.html" %}
{% block title %}Регистрация{% endblock %}
{% block content %}
{% include "includes/form.html" %}
{% endblock %}

108
CineSync/users/forms.py Normal file
View File

@ -0,0 +1,108 @@
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import (
AuthenticationForm,
PasswordChangeForm,
PasswordResetForm,
SetPasswordForm,
UserChangeForm,
UserCreationForm,
)
from users.models import Profile
__all__ = []
class CustomAuthenticationForm(AuthenticationForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(forms.ModelForm):
model = Profile
class CustomPasswordChangeForm(PasswordChangeForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(forms.ModelForm):
fields = ('old_password', 'new_password', 'approve_new_password')
class CustomSetPasswordForm(SetPasswordForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(forms.ModelForm):
fields = ('old_password', 'new_password', 'approve_new_password')
class CustomPasswordResetForm(PasswordResetForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(forms.ModelForm):
fields = ('old_password', 'new_password', 'approve_new_password')
class SignUpForm(UserCreationForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(UserCreationForm.Meta):
fields = ('username', 'email')
class ProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(forms.ModelForm):
model = Profile
fields = [
model.birthday.field.name,
model.image.field.name,
]
class CustomUserChangeForm(UserChangeForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(UserChangeForm.Meta):
model = get_user_model()
fields = [
model.username.field.name,
model.first_name.field.name,
model.last_name.field.name,
]
class UserForm(forms.ModelForm):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
for field in self.visible_fields():
field.field.widget.attrs['class'] = 'form-control'
class Meta(forms.ModelForm):
model = get_user_model()
fields = [
model.username.field.name,
model.first_name.field.name,
model.last_name.field.name,
]

83
CineSync/users/urls.py Normal file
View File

@ -0,0 +1,83 @@
from django.contrib.auth import views
from django.contrib.auth.decorators import login_required
from django.urls import path
from django.urls import reverse_lazy
from users.forms import (
CustomAuthenticationForm,
CustomPasswordChangeForm,
CustomPasswordResetForm,
CustomSetPasswordForm,
)
from users.views import profile, signup
app_name = 'users'
urlpatterns = [
path(
'login/',
views.LoginView.as_view(
template_name='users/login.html',
authentication_form=CustomAuthenticationForm,
),
name='login',
),
path(
'logout/',
views.LogoutView.as_view(
template_name='users/login.html',
),
name='logout',
),
path(
'password_change/',
views.PasswordChangeView.as_view(
template_name='users/password_change.html',
form_class=CustomPasswordChangeForm,
success_url=reverse_lazy('users:password_change_done'),
),
name='password_change',
),
path(
'password_change/done/',
views.PasswordChangeDoneView.as_view(
template_name='users/password_change_done.html',
),
name='password_change_done',
),
path(
'password_reset/',
views.PasswordResetView.as_view(
template_name='users/password_reset.html',
email_template_name='users/password_reset_email.html',
form_class=CustomPasswordResetForm,
success_url=reverse_lazy('users:password_reset_done'),
),
name='password_reset',
),
path(
'password_reset/done/',
views.PasswordResetDoneView.as_view(
template_name='users/password_reset_done.html',
),
name='password_reset_done',
),
path(
'password_reset_confirm/<uidb64>/<token>/',
views.PasswordResetConfirmView.as_view(
form_class=CustomSetPasswordForm,
template_name='users/password_reset_confirm.html',
success_url=reverse_lazy('users:password_reset_confirm_complete'),
),
name='password_reset_confirm',
),
path(
'password_reset_complete/done/',
views.PasswordResetCompleteView.as_view(
template_name='users/password_reset_complete.html',
),
name='password_reset_complete',
),
path('signup/', signup, name='signup'),
path('profile/', login_required(profile), name='profile'),
]

View File

@ -1,3 +1,95 @@
from django.shortcuts import render from django.conf import settings
from django.contrib import messages
from django.core.mail import send_mail
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.translation import gettext as _
from django.views.generic import View
# Create your views here. from users.forms import SignUpForm, ProfileForm, UserForm
from users.models import Profile
__all__ = []
def signup(request):
form = SignUpForm(request.POST)
template = "users/signup.html"
context = {
"form": form,
}
if request.method == 'GET':
return render(request, template, context)
if form.is_valid():
user = form.save(commit=False)
user.save()
Profile.objects.create(user=user)
user.profile.save()
messages.success(request, _("Пользователь упешно создан"))
return redirect(reverse("users:login"))
return render(request, template, context)
def profile(request):
profile_form = ProfileForm(
request.POST or None,
instance=request.user.profile,
)
user_form = UserForm(
request.POST or None,
instance=request.user,
)
if request.method == 'GET':
return render(
request,
"users/profile.html",
{
"profile_form": profile_form,
"user_form": user_form,
"user": request.user,
},
)
if all((profile_form.is_valid(), user_form.is_valid())):
profile_form.save()
user_form.save()
return render(
request,
"users/profile.html",
{
"profile_form": profile_form,
"user_form": user_form,
"user": request.user,
},
)
class SignupView(View):
def get(self, request):
form = SignUpForm()
template = "users/signup.html"
context = {
"form": form,
}
return render(request, template, context)
def post(self, request):
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.is_active = settings.DEFAULT_USER_IS_ACTIVE
user.save()
Profile.objects.create(user=user)
user.profile.save()
messages.success(request, _("Пользователь упешно создан"))
return redirect(reverse("users:login"))
template = "users/signup.html"
context = {
"form": form,
}
return render(request, template, context)