поправил форматирование
This commit is contained in:
parent
84e66e7978
commit
feb1493ecd
2
.flake8
2
.flake8
@ -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__,
|
||||
|
||||
@ -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',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"',
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -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="Дата релиза",
|
||||
),
|
||||
),
|
||||
(
|
||||
|
||||
@ -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="Имя",
|
||||
),
|
||||
),
|
||||
(
|
||||
|
||||
@ -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 = [
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@ -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'),
|
||||
]
|
||||
|
||||
@ -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,
|
||||
)
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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 = [
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@ -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'),
|
||||
]
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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']
|
||||
)
|
||||
|
||||
@ -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="Количество кресел в ряду",
|
||||
),
|
||||
),
|
||||
|
||||
@ -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="Цена билета",
|
||||
),
|
||||
),
|
||||
|
||||
@ -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="Дата и время начала сеанса",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@ -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'
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@ -6,7 +6,6 @@ from django.urls import reverse_lazy
|
||||
from users.forms import (
|
||||
CustomAuthenticationForm,
|
||||
CustomPasswordChangeForm,
|
||||
CustomSetPasswordForm,
|
||||
)
|
||||
from users.views import profile, signup
|
||||
|
||||
|
||||
@ -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,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
[tool.black]
|
||||
line-length = 79
|
||||
skip-string-normalization = 'true'
|
||||
exclude = '''
|
||||
venv/
|
||||
.git/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user