Create registration, login and profile forms
This commit is contained in:
parent
bd89672f89
commit
6ea3b78449
@ -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/"
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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')
|
||||||
]
|
]
|
||||||
|
|||||||
@ -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
6
CineSync/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
CineSync/static/css/bootstrap.min.css.map
Normal file
1
CineSync/static/css/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
7
CineSync/static/js/bootstrap.bundle.min.js
vendored
Normal file
7
CineSync/static/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
CineSync/static/js/bootstrap.bundle.min.js.map
Normal file
1
CineSync/static/js/bootstrap.bundle.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -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>
|
||||||
32
CineSync/templates/users/login.html
Normal file
32
CineSync/templates/users/login.html
Normal 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 %}
|
||||||
@ -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 %}
|
||||||
5
CineSync/templates/users/signup.html
Normal file
5
CineSync/templates/users/signup.html
Normal 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
108
CineSync/users/forms.py
Normal 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
83
CineSync/users/urls.py
Normal 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'),
|
||||||
|
]
|
||||||
@ -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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user