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/'
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
BASE_DIR / 'static',
|
||||
]
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
|
||||
MEDIA_URL = "/media/"
|
||||
|
||||
@ -7,6 +7,9 @@ from django.urls import include, path
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
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:
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
from django.urls import path
|
||||
|
||||
from films import views
|
||||
from films.views import films_list, film_details
|
||||
|
||||
app_name = 'films'
|
||||
urlpatterns = [
|
||||
path('', views.films_list, name='main'),
|
||||
path('<int:film_id>/', views.film_details, name='film_details')
|
||||
path('', films_list, name='main'),
|
||||
path('<int:film_id>/', film_details, name='film_details')
|
||||
]
|
||||
|
||||
@ -6,11 +6,10 @@ from films.models import Film
|
||||
|
||||
def films_list(request: HttpResponse) -> HttpResponse:
|
||||
films = Film.objects.released()
|
||||
context = {'films': films}
|
||||
return render(
|
||||
request,
|
||||
'films/films_list.html',
|
||||
context,
|
||||
{'films': films},
|
||||
)
|
||||
|
||||
|
||||
@ -21,7 +20,7 @@ def film_details(request: HttpResponse, film_id: int) -> HttpResponse:
|
||||
)
|
||||
return render(
|
||||
request,
|
||||
"catalog/film_details.html",
|
||||
{"item": item},
|
||||
'films/film_details.html',
|
||||
{'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