поправил форматирование

This commit is contained in:
Андрей Дувакин 2024-04-22 22:54:03 +05:00
parent 84e66e7978
commit feb1493ecd
38 changed files with 215 additions and 152 deletions

View File

@ -1,7 +1,7 @@
[flake8]
max-line-length = 80
import-order-style = google
application-import-names = timetable, tickets, home, films
application-import-names = timetable, tickets, home, films, users
exclude =
.git,
__pycache__,

View File

@ -1,5 +1,6 @@
import os
from pathlib import Path
from dotenv import load_dotenv
load_dotenv()
@ -83,21 +84,25 @@ DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
},
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
'NAME': 'django.contrib.auth.'
'password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'NAME': 'django.contrib.auth.'
'password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
'NAME': 'django.contrib.auth.'
'password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
'NAME': 'django.contrib.auth.'
'password_validation.NumericPasswordValidator',
},
]

View File

@ -10,15 +10,15 @@ urlpatterns = [
path('films/', include('films.urls'), name='films'),
path('timetable/', include('timetable.urls'), name='timetable'),
path('tickets/', include('tickets.urls'), name='tickets'),
path("auth/", include("users.urls"), name="auth"),
path("auth/", include("django.contrib.auth.urls"), name="auth"),
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)
urlpatterns += static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT,
)
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT,
)
if settings.DEBUG:
import debug_toolbar

View File

@ -1,7 +1,7 @@
from django.contrib import admin
from django.utils.safestring import mark_safe
from films.models import Film, Genre, Actor, Director, Country
from films.models import Actor, Country, Director, Film, Genre
@admin.register(Film)
@ -13,7 +13,7 @@ class FilmAdmin(admin.ModelAdmin):
'get_image',
]
readonly_fields = ("get_image",)
readonly_fields = ('get_image',)
filter_horizontal = [
Film.genres.field.name,
@ -28,7 +28,7 @@ class FilmAdmin(admin.ModelAdmin):
def get_image(self, obj):
return mark_safe(
f"<img src='{obj.image_tmb()}' width='50' height='50'",
f'<img src="{obj.image_tmb()}" width="50" height="50"',
)

View File

@ -62,14 +62,17 @@ class Migration(migrations.Migration):
"duration",
models.IntegerField(
help_text="Продолжительность фильма (в минутах)",
validators=[django.core.validators.MinValueValidator(0)],
validators=[
django.core.validators.MinValueValidator(0)
],
verbose_name="Продолжительность",
),
),
(
"release_date",
models.DateField(
help_text="Дата выхода фильма", verbose_name="Дата релиза"
help_text="Дата выхода фильма",
verbose_name="Дата релиза",
),
),
(

View File

@ -25,7 +25,9 @@ class Migration(migrations.Migration):
(
"first_name",
models.CharField(
help_text="Имя актера", max_length=100, verbose_name="Имя"
help_text="Имя актера",
max_length=100,
verbose_name="Имя",
),
),
(
@ -85,7 +87,9 @@ class Migration(migrations.Migration):
(
"first_name",
models.CharField(
help_text="Имя режиссера", max_length=100, verbose_name="Имя"
help_text="Имя режиссера",
max_length=100,
verbose_name="Имя",
),
),
(

View File

@ -6,7 +6,10 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("films", "0006_actor_country_director_film_actors_film_countries_and_more"),
(
"films",
"0006_actor_country_director_film_actors_film_countries_and_more",
),
]
operations = [

View File

@ -1,15 +1,16 @@
import time
from datetime import timedelta
import time
import sorl
from django.core.validators import MinValueValidator
from django.db.models import (
Model,
CharField,
IntegerField,
DateField,
ImageField,
IntegerField,
Manager,
ManyToManyField,
Manager, ImageField, Min,
Min,
Model,
)
from django.utils import timezone
from django.utils.safestring import mark_safe
@ -18,36 +19,51 @@ from sorl.thumbnail import get_thumbnail
class FilmManager(Manager):
def released(self):
return super().get_queryset().filter(
release_date__lt=timezone.now(),
return (
super()
.get_queryset()
.filter(
release_date__lt=timezone.now(),
)
)
def will_be_shown(self):
current_datetime = timezone.now()
films_with_sessions = super().get_queryset().filter(
sessions__start_datetime__gte=current_datetime,
).annotate(
nearest_session=Min('sessions__start_datetime')
).order_by('nearest_session')
return films_with_sessions
return (
super()
.get_queryset()
.filter(
sessions__start_datetime__gte=current_datetime,
)
.annotate(nearest_session=Min('sessions__start_datetime'))
.order_by('nearest_session')
)
def on_main(self):
current_datetime = timezone.now()
end_datetime = current_datetime + timedelta(days=5)
films_with_sessions = super().get_queryset().filter(
sessions__start_datetime__gte=current_datetime,
sessions__start_datetime__lte=end_datetime,
).exclude(image=None).distinct().only(
Film.name.field.name,
Film.image.field.name,
Film.description.field.name,
queryset = super().get_queryset()
films_with_sessions = (
queryset.filter(
sessions__start_datetime__gte=current_datetime,
sessions__start_datetime__lte=end_datetime,
)
.exclude(image=None)
.distinct()
.only(
Film.name.field.name,
Film.image.field.name,
Film.description.field.name,
)
)
if films_with_sessions.count() > 5:
films_with_sessions = films_with_sessions[:5]
elif films_with_sessions.count() > 0:
films_with_sessions = films_with_sessions[:films_with_sessions.count()]
films_with_sessions = films_with_sessions[
: films_with_sessions.count()
]
return films_with_sessions
@ -209,23 +225,23 @@ class Film(Model):
)
def get_image_300x300(self):
return sorl.thumbnail.get_thumbnail(
return get_thumbnail(
self.image,
"300x300",
crop="center",
'300x300',
crop='center',
quality=51,
)
def image_tmb(self):
if self.image:
tag = f"{self.get_image_300x300().url}"
tag = f'{self.get_image_300x300().url}'
return mark_safe(tag)
return "Нет изорбражения"
return 'Нет изорбражения'
image_tmb.field_name = "image_tmb"
image_tmb.field_name = 'image_tmb'
image_tmb.allow_tags = True
image_tmb.short_description = "Превью"
image_tmb.short_description = 'Превью'
class Meta:
db_table = 'films_films'

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

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

View File

@ -1,5 +1,5 @@
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.shortcuts import get_object_or_404, render
from films.models import Film
from timetable.models import FilmSession
@ -19,16 +19,21 @@ def film_details(request: HttpResponse, film_id: int) -> HttpResponse:
Film.objects.released(),
id=film_id,
)
film_sessions = FilmSession.objects.nearest_timetable().filter(film_id=film_id)
film_sessions = FilmSession.objects.nearest_timetable().filter(
film_id=film_id,
)
sessions_by_date_and_film = {}
for session in film_sessions:
session_date = session.start_datetime.date()
if session_date not in sessions_by_date_and_film:
sessions_by_date_and_film[session_date] = {}
film_sessions_for_date = sessions_by_date_and_film[session_date]
if session.film not in film_sessions_for_date:
film_sessions_for_date[session.film] = []
film_sessions_for_date[session.film].append(session)
for session_date, session_films in sessions_by_date_and_film.items():
@ -36,6 +41,7 @@ def film_details(request: HttpResponse, film_id: int) -> HttpResponse:
sessions_by_date_and_film[session_date][session_film].sort(
key=lambda sorted_session: sorted_session.start_datetime,
)
context = {
'film_sessions': sessions_by_date_and_film,
'item': item,
@ -45,4 +51,3 @@ def film_details(request: HttpResponse, film_id: int) -> HttpResponse:
'films/film_details.html',
context,
)

View File

@ -1,3 +0,0 @@
from django.contrib import admin
# Register your models here.

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -3,6 +3,7 @@ from datetime import date
from django.http import HttpResponse
from django.shortcuts import render
from films.models import Film
from timetable.models import FilmSession
@ -16,9 +17,11 @@ def homepage(request):
session_date = session.start_datetime.date()
if session_date not in sessions_by_date_and_film:
sessions_by_date_and_film[session_date] = {}
film_sessions_for_date = sessions_by_date_and_film[session_date]
if session.film not in film_sessions_for_date:
film_sessions_for_date[session.film] = []
film_sessions_for_date[session.film].append(session)
for session_date, session_films in sessions_by_date_and_film.items():
@ -35,7 +38,7 @@ def homepage(request):
'films_sessions': sessions_by_date_and_film,
'today': date.today(),
'tomorrow': date.today() + datetime.timedelta(days=1),
}
},
)
return HttpResponse(
template,

View File

@ -1,20 +1,19 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'CineSync.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
'available on your PYTHONPATH environment variable? Did you '
'forget to activate a virtual environment?',
) from exc
execute_from_command_line(sys.argv)

View File

@ -1,6 +1,6 @@
from django.contrib import admin
from tickets.models import Ticket, Order
from tickets.models import Order, Ticket
class TicketAdminInline(admin.StackedInline):

View File

@ -6,7 +6,10 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("tickets", "0006_remove_ticket_profile_remove_ticket_session_and_more"),
(
"tickets",
"0006_remove_ticket_profile_remove_ticket_session_and_more",
),
]
operations = [

View File

@ -1,5 +1,12 @@
from django.db.models import ForeignKey, CASCADE, Model, IntegerField, DateTimeField, Manager
from django.core.validators import MinValueValidator
from django.db.models import (
CASCADE,
DateTimeField,
ForeignKey,
IntegerField,
Manager,
Model,
)
from timetable.models import FilmSession
from users.models import Profile
@ -7,8 +14,7 @@ from users.models import Profile
class TicketManager(Manager):
def get_tickets_for_session(self, session_id):
tickets = super().get_queryset().filter(order__session_id=session_id)
return tickets
return super().get_queryset().filter(order__session_id=session_id)
class Order(Model):

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,10 +1,10 @@
from django.urls import path
from tickets.views import order_success, my_orders
from tickets.views import my_orders, order_success
app_name = 'tickets'
urlpatterns = [
path('order/success', order_success, name='order_success'),
path('my/', my_orders, name='my_orders')
path('my/', my_orders, name='my_orders'),
]

View File

@ -1,7 +1,7 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_list_or_404
from django.shortcuts import render
from tickets.models import Order, Ticket
from tickets.models import Order
def order_success(request):
@ -11,16 +11,11 @@ def order_success(request):
@login_required
def my_orders(request):
user = request.user
orders = Order.objects.filter(
profile__id=user.profile.id,
).select_related(
'session',
'session__film',
).prefetch_related(
'tickets',
).order_by(
'-datetime_order'
)
queryset = Order.objects.filter(profile__id=user.profile.id)
queryset = queryset.select_related('session', 'session__film')
queryset = queryset.prefetch_related('tickets')
orders = queryset.order_by('-datetime_order')
context = {
'my_orders': orders,
}

View File

@ -1,6 +1,6 @@
from django.contrib import admin
from timetable.models import Auditorium, Row, FilmSession
from timetable.models import Auditorium, FilmSession, Row
class RowAdminInline(admin.StackedInline):

View File

@ -1,9 +1,8 @@
import pprint
from json import loads
from django import forms
from timetable.models import Auditorium, Row
from timetable.models import Auditorium
class SeatSelectionForm(forms.Form):
@ -17,13 +16,19 @@ class SeatSelectionForm(forms.Form):
for i, row in enumerate(auditorium.rows.all(), start=1):
for seat in range(1, row.column_count + 1):
choices.append((f'[{seat}, {str(i)}]', f'[{seat}, {str(i)}]'))
self.fields['selected_seats'].choices = choices
for field in self.visible_fields():
field.field.widget.attrs.update({"class": "seat_checkbox"})
field.field.widget.attrs.update({'class': 'seat_checkbox'})
def clean_selected_seats(self):
selected_seats = self.cleaned_data['selected_seats']
if isinstance(selected_seats, list) and all(isinstance(item, str) for item in selected_seats):
selected_seats = [loads(field) for field in selected_seats]
return selected_seats
return (
[loads(field) for field in self.cleaned_data['selected_seats']]
if isinstance(self.cleaned_data['selected_seats'], list)
and all(
isinstance(item, str)
for item in self.cleaned_data['selected_seats']
)
else self.cleaned_data['selected_seats']
)

View File

@ -26,12 +26,16 @@ class Migration(migrations.Migration):
),
(
"number",
models.CharField(max_length=20, verbose_name="Номер кинозала"),
models.CharField(
max_length=20, verbose_name="Номер кинозала"
),
),
(
"row_count",
models.IntegerField(
validators=[django.core.validators.MinValueValidator(1)],
validators=[
django.core.validators.MinValueValidator(1)
],
verbose_name="Количество рядов кресел в зале",
),
),
@ -57,14 +61,18 @@ class Migration(migrations.Migration):
(
"row_number",
models.IntegerField(
validators=[django.core.validators.MinValueValidator(1)],
validators=[
django.core.validators.MinValueValidator(1)
],
verbose_name="Номер ряда",
),
),
(
"column_count",
models.IntegerField(
validators=[django.core.validators.MinValueValidator(1)],
validators=[
django.core.validators.MinValueValidator(1)
],
verbose_name="Количество кресел в ряду",
),
),

View File

@ -31,12 +31,16 @@ class Migration(migrations.Migration):
),
(
"start_datetime",
models.DateTimeField(verbose_name="Дата и время начала сеанса"),
models.DateTimeField(
verbose_name="Дата и время начала сеанса"
),
),
(
"price",
models.FloatField(
validators=[django.core.validators.MinValueValidator(1)],
validators=[
django.core.validators.MinValueValidator(1)
],
verbose_name="Цена билета",
),
),

View File

@ -14,7 +14,9 @@ class Migration(migrations.Migration):
model_name="filmsession",
name="end_datetime",
field=models.DateTimeField(
blank=True, null=True, verbose_name="Дата и время начала сеанса"
blank=True,
null=True,
verbose_name="Дата и время начала сеанса",
),
),
]

View File

@ -1,7 +1,16 @@
from datetime import timedelta
from django.db.models import Model, CharField, IntegerField, CASCADE, DateTimeField, FloatField, ForeignKey, Manager
from django.core.validators import MinValueValidator
from django.db.models import (
CASCADE,
CharField,
DateTimeField,
FloatField,
ForeignKey,
IntegerField,
Manager,
Model,
)
from django.utils import timezone
from films.models import Film
@ -11,34 +20,23 @@ class FilmSessionsManager(Manager):
def nearest_timetable(self):
current_datetime = timezone.now()
end_datetime = current_datetime + timedelta(days=5)
films_sessions = super().get_queryset().select_related(
'film',
).prefetch_related(
'film__genres',
'film__countries',
).filter(
queryset = super().get_queryset()
queryset = queryset.select_related('film')
queryset = queryset.prefetch_related('film__genres', 'film__countries')
queryset = queryset.filter(
start_datetime__gte=current_datetime,
start_datetime__lte=end_datetime,
).order_by(
FilmSession.start_datetime.field.name,
)
return films_sessions
return queryset.order_by(FilmSession.start_datetime.field.name)
def all_timetable(self):
current_datetime = timezone.now()
films_sessions = super().get_queryset().select_related(
'film',
).prefetch_related(
'film__genres',
'film__countries',
).filter(
start_datetime__gte=current_datetime,
).prefetch_related(
FilmSession.film.field.name,
).order_by(
FilmSession.start_datetime.field.name,
)
return films_sessions
queryset = super().get_queryset()
queryset = queryset.select_related('film')
queryset = queryset.prefetch_related('film__genres', 'film__countries')
queryset = queryset.filter(start_datetime__gte=current_datetime)
queryset = queryset.prefetch_related(FilmSession.film.field.name)
return queryset.order_by(FilmSession.start_datetime.field.name)
class Auditorium(Model):
@ -121,11 +119,17 @@ class FilmSession(Model):
)
def __str__(self):
return f'{self.film.name} - {str(self.start_datetime)} - {self.auditorium}'
return (
f'{self.film.name} - {str(self.start_datetime)}'
f' - {self.auditorium}'
)
def save(self, *args, **kwargs):
if self.start_datetime and self.film.duration:
self.end_datetime = self.start_datetime + timedelta(minutes=self.film.duration)
self.end_datetime = self.start_datetime + timedelta(
minutes=self.film.duration,
)
super().save(*args, **kwargs)
class Meta:

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -1,6 +1,6 @@
from django.urls import path
from timetable.views import timetable_view, session_view
from timetable.views import session_view, timetable_view
app_name = 'time_table'

View File

@ -4,13 +4,13 @@ from datetime import date
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils import timezone
from timetable.models import FilmSession, Row
from timetable.forms import SeatSelectionForm
from tickets.models import Order, Ticket
from timetable.forms import SeatSelectionForm
from timetable.models import FilmSession
def timetable_view(request):
@ -21,9 +21,11 @@ def timetable_view(request):
session_date = session.start_datetime.date()
if session_date not in sessions_by_date_and_film:
sessions_by_date_and_film[session_date] = {}
film_sessions_for_date = sessions_by_date_and_film[session_date]
if session.film not in film_sessions_for_date:
film_sessions_for_date[session.film] = []
film_sessions_for_date[session.film].append(session)
for session_date, session_films in sessions_by_date_and_film.items():
@ -31,6 +33,7 @@ def timetable_view(request):
sessions_by_date_and_film[session_date][session_film].sort(
key=lambda sorted_session: sorted_session.start_datetime,
)
template = render(
request,
'timetable/timetable.html',
@ -38,7 +41,7 @@ def timetable_view(request):
'films_sessions': sessions_by_date_and_film,
'today': date.today(),
'tomorrow': date.today() + datetime.timedelta(days=1),
}
},
)
return HttpResponse(
template,
@ -60,7 +63,10 @@ def session_view(request, sess_id):
height = round(session.auditorium.rows.count() * 4 + 7)
tickets = Ticket.objects.get_tickets_for_session(session.pk)
occupied_seats = [f"{str(ticket.row_number)}-{str(ticket.column_number)}" for ticket in tickets]
occupied_seats = [
f'{str(ticket.row_number)}-{str(ticket.column_number)}'
for ticket in tickets
]
if request.method == 'POST':
form = SeatSelectionForm(request.POST, auditorium=session.auditorium)

View File

@ -1,6 +1,5 @@
from django import forms
from django.contrib.auth import get_user_model
from django.forms import DateInput, ModelForm
from django.contrib.auth.forms import (
AuthenticationForm,
PasswordChangeForm,
@ -8,6 +7,7 @@ from django.contrib.auth.forms import (
UserChangeForm,
UserCreationForm,
)
from django.forms import DateInput, ModelForm
from users.models import Profile

View File

@ -30,12 +30,16 @@ class Migration(migrations.Migration):
(
"birthday",
models.DateField(
blank=True, null=True, verbose_name="Дата рождения пользователя"
blank=True,
null=True,
verbose_name="Дата рождения пользователя",
),
),
(
"role",
models.CharField(max_length=20, verbose_name="Роль пользователя"),
models.CharField(
max_length=20, verbose_name="Роль пользователя"
),
),
(
"image",

View File

@ -19,7 +19,9 @@ class Migration(migrations.Migration):
model_name="profile",
name="genres",
field=models.ManyToManyField(
related_name="profiles", related_query_name="profiles", to="films.genre"
related_name="profiles",
related_query_name="profiles",
to="films.genre",
),
),
]

View File

@ -1,7 +1,15 @@
import time
from django.conf import settings
from django.db.models import Model, OneToOneField, CASCADE, DateField, CharField, ImageField, ManyToManyField
from django.db.models import (
CASCADE,
CharField,
DateField,
ImageField,
ManyToManyField,
Model,
OneToOneField,
)
from django.utils.safestring import mark_safe
from sorl.thumbnail import get_thumbnail

View File

@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.

View File

@ -6,7 +6,6 @@ from django.urls import reverse_lazy
from users.forms import (
CustomAuthenticationForm,
CustomPasswordChangeForm,
CustomSetPasswordForm,
)
from users.views import profile, signup

View File

@ -1,12 +1,9 @@
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
from users.forms import SignUpForm, ProfileForm, UserForm
from users.forms import ProfileForm, SignUpForm, UserForm
from users.models import Profile
__all__ = []
@ -59,4 +56,3 @@ def profile(request):
'user': request.user,
},
)

View File

@ -1,5 +1,6 @@
[tool.black]
line-length = 79
skip-string-normalization = 'true'
exclude = '''
venv/
.git/