Merge branch 'refs/heads/ivan' into andrei
# Conflicts: # CineSync/CineSync/urls.py # CineSync/templates/base.html
This commit is contained in:
commit
a286ded289
@ -7,7 +7,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", default="google")
|
||||
|
||||
DEBUG = os.environ.get("DJANGO_DEBUG", default="false")
|
||||
DEBUG = os.getenv("DJANGO_DEBUG", default="false")
|
||||
DEBUG = DEBUG.lower().strip() in ("true", "yes", "1", "y", "t")
|
||||
|
||||
AUTH_USER_MODEL = "auth.User"
|
||||
|
||||
@ -3,9 +3,14 @@ from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('', include('home.urls')),
|
||||
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"),
|
||||
|
||||
]
|
||||
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
||||
@ -1,7 +1,22 @@
|
||||
from django.db.models import Model, CharField, IntegerField, DateField, ManyToManyField
|
||||
from django.db.models import (
|
||||
Model,
|
||||
CharField,
|
||||
IntegerField,
|
||||
DateField,
|
||||
ManyToManyField,
|
||||
Manager,
|
||||
)
|
||||
from django.utils import timezone
|
||||
from django.core.validators import MinValueValidator
|
||||
|
||||
|
||||
class FilmManager(Manager):
|
||||
def released(self):
|
||||
return super().get_queryset().filter(
|
||||
release_date__lt=timezone.now(),
|
||||
)
|
||||
|
||||
|
||||
class Genre(Model):
|
||||
name = CharField(
|
||||
'Название',
|
||||
@ -17,6 +32,8 @@ class Genre(Model):
|
||||
|
||||
|
||||
class Film(Model):
|
||||
objects = FilmManager()
|
||||
|
||||
name = CharField(
|
||||
'Название',
|
||||
help_text='Название фильма',
|
||||
|
||||
9
CineSync/films/urls.py
Normal file
9
CineSync/films/urls.py
Normal file
@ -0,0 +1,9 @@
|
||||
from django.urls import path
|
||||
|
||||
from films.views import films_list, film_details
|
||||
|
||||
app_name = 'films'
|
||||
urlpatterns = [
|
||||
path('', films_list, name='main'),
|
||||
path('<int:film_id>/', film_details, name='film_details')
|
||||
]
|
||||
@ -1,3 +1,26 @@
|
||||
from django.shortcuts import render
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
|
||||
from films.models import Film
|
||||
|
||||
|
||||
def films_list(request: HttpResponse) -> HttpResponse:
|
||||
films = Film.objects.released()
|
||||
return render(
|
||||
request,
|
||||
'films/films_list.html',
|
||||
{'films': films},
|
||||
)
|
||||
|
||||
|
||||
def film_details(request: HttpResponse, film_id: int) -> HttpResponse:
|
||||
item = get_object_or_404(
|
||||
Film.objects.released(),
|
||||
id=film_id,
|
||||
)
|
||||
return render(
|
||||
request,
|
||||
'films/film_details.html',
|
||||
{'item': item},
|
||||
)
|
||||
|
||||
# Create your views here.
|
||||
|
||||
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
@ -1,12 +1,23 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{% endblock title %}</title>
|
||||
<link href="{% static 'css/bootstrap/bootstrap.min.css' %}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="{% static 'css/header.css' %}"/>
|
||||
<link rel="stylesheet" href="{% static 'css/footer.css' %}"/>
|
||||
<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' %}
|
||||
|
||||
0
CineSync/templates/films/film_details.html
Normal file
0
CineSync/templates/films/film_details.html
Normal file
0
CineSync/templates/films/films_list.html
Normal file
0
CineSync/templates/films/films_list.html
Normal file
17
CineSync/templates/includes/form.html
Normal file
17
CineSync/templates/includes/form.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% 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>
|
||||
0
CineSync/templates/tickets/ticket_details.html
Normal file
0
CineSync/templates/tickets/ticket_details.html
Normal file
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 %}
|
||||
48
CineSync/templates/users/profile.html
Normal file
48
CineSync/templates/users/profile.html
Normal 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 %}
|
||||
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