сделал главную страничку
This commit is contained in:
parent
409d81b82f
commit
4f9b2e2d2b
@ -1,6 +1,5 @@
|
|||||||
import time
|
import time
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from random import shuffle
|
|
||||||
|
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Model,
|
Model,
|
||||||
@ -12,6 +11,7 @@ from django.db.models import (
|
|||||||
)
|
)
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
|
from sorl.thumbnail import get_thumbnail
|
||||||
|
|
||||||
|
|
||||||
class FilmManager(Manager):
|
class FilmManager(Manager):
|
||||||
@ -23,11 +23,19 @@ class FilmManager(Manager):
|
|||||||
def on_main(self):
|
def on_main(self):
|
||||||
current_datetime = timezone.now()
|
current_datetime = timezone.now()
|
||||||
end_datetime = current_datetime + timedelta(days=5)
|
end_datetime = current_datetime + timedelta(days=5)
|
||||||
films_with_sessions = Film.objects.filter(
|
films_with_sessions = super().get_queryset().filter(
|
||||||
sessions__start_datetime__gte=current_datetime,
|
sessions__start_datetime__gte=current_datetime,
|
||||||
sessions__start_datetime__lte=end_datetime,
|
sessions__start_datetime__lte=end_datetime,
|
||||||
).exclude(image=None).distinct()
|
).exclude(image=None).distinct().only(
|
||||||
shuffle(list(films_with_sessions))
|
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()]
|
||||||
return films_with_sessions
|
return films_with_sessions
|
||||||
|
|
||||||
|
|
||||||
@ -49,6 +57,9 @@ class Film(Model):
|
|||||||
def get_upload_path(self, filename):
|
def get_upload_path(self, filename):
|
||||||
return f'users/films/{self.pk}/{time.time()}_{filename}'
|
return f'users/films/{self.pk}/{time.time()}_{filename}'
|
||||||
|
|
||||||
|
def get_image_url(self):
|
||||||
|
return self.image.url
|
||||||
|
|
||||||
objects = FilmManager()
|
objects = FilmManager()
|
||||||
|
|
||||||
name = CharField(
|
name = CharField(
|
||||||
|
|||||||
@ -1,16 +1,37 @@
|
|||||||
|
import datetime
|
||||||
|
from datetime import date
|
||||||
|
from collections import defaultdict
|
||||||
|
from pprint import pprint
|
||||||
|
from random import shuffle
|
||||||
|
|
||||||
|
from django.db.models import QuerySet
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
from films.models import Film
|
from films.models import Film
|
||||||
|
from timetable.models import FilmSession
|
||||||
|
|
||||||
|
|
||||||
def homepage(request):
|
def homepage(request):
|
||||||
films = Film.objects.on_main()
|
films = Film.objects.on_main()
|
||||||
|
film_sessions = FilmSession.objects.nearest_timetable()
|
||||||
|
sessions_by_date_and_film = defaultdict(lambda: defaultdict(list))
|
||||||
|
|
||||||
|
for session in film_sessions:
|
||||||
|
session_date = session.start_datetime.date()
|
||||||
|
sessions_by_date_and_film[session_date][session.film].append(session)
|
||||||
|
|
||||||
|
for session in film_sessions:
|
||||||
|
session_date = session.start_datetime.date()
|
||||||
|
sessions_by_date_and_film[session_date] = dict(sessions_by_date_and_film[session_date])
|
||||||
|
|
||||||
template = render(
|
template = render(
|
||||||
request,
|
request,
|
||||||
'home/homepage.html',
|
'home/homepage.html',
|
||||||
context={
|
context={
|
||||||
'films_preview': films
|
'films_preview': films,
|
||||||
|
'films_sessions': dict(sessions_by_date_and_film),
|
||||||
|
'tomorrow': date.today() + datetime.timedelta(days=1)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
height: 30vw;
|
height: 30vw;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.film_card_image {
|
.film_preview_image {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
height: 30vw !important;
|
height: 30vw !important;
|
||||||
width: 70% !important;
|
width: 70% !important;
|
||||||
@ -21,4 +21,82 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: 15%;
|
margin-left: 15%;
|
||||||
|
}
|
||||||
|
.header_title {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #eaeaea;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 2vw;
|
||||||
|
}
|
||||||
|
.timetable_block {
|
||||||
|
margin-top: 10vw;
|
||||||
|
height: 100vw;
|
||||||
|
}
|
||||||
|
.tab_btn {
|
||||||
|
color: #eaeaea !important;
|
||||||
|
}
|
||||||
|
.tab_btn.active {
|
||||||
|
color: #0d1d3a !important;
|
||||||
|
}
|
||||||
|
.timetable_body.active {
|
||||||
|
margin-top: 1vw;
|
||||||
|
margin-bottom: 10vw;
|
||||||
|
padding-top: 2vw;
|
||||||
|
padding-bottom: 2vw;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.film_card {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #eaeaea;
|
||||||
|
margin-top: 1vw;
|
||||||
|
margin-bottom: 1vw;
|
||||||
|
border-radius: 3vw;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
.film_card_image {
|
||||||
|
object-fit: cover;
|
||||||
|
height: 10vw !important;
|
||||||
|
width: 10vw !important;
|
||||||
|
border-radius: 3vw;
|
||||||
|
}
|
||||||
|
.film_card_column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-around;
|
||||||
|
height: 10vw;
|
||||||
|
margin-left: 2vw;
|
||||||
|
}
|
||||||
|
.film_card_column_item {
|
||||||
|
height: 20%;
|
||||||
|
}
|
||||||
|
.film_card_row {
|
||||||
|
height: 80%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
.film_session {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: rgb(255, 91, 119);
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.session_time {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.session_time:hover {
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
@ -20,6 +20,7 @@ header {
|
|||||||
.header_container {
|
.header_container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
z-index: 100;
|
||||||
}
|
}
|
||||||
.nav-item {
|
.nav-item {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{% static 'css/home/homepage.css' %}" rel="stylesheet">
|
<link href="{% static 'css/home/homepage.css' %}" rel="stylesheet">
|
||||||
<div class="carousel_films">
|
<div class="carousel_films">
|
||||||
|
<h1 class="header_title">Сейчас в прокате</h1>
|
||||||
<div id="carouselWhite" class="carousel carousel slide">
|
<div id="carouselWhite" class="carousel carousel slide">
|
||||||
{{films}}
|
|
||||||
<div class="carousel-indicators">
|
<div class="carousel-indicators">
|
||||||
{% for film in films_preview %}
|
{% for film in films_preview %}
|
||||||
<button type="button" data-bs-target="#carouselWhite" data-bs-slide-to="{{ forloop.counter0 }}"
|
<button type="button" data-bs-target="#carouselWhite" data-bs-slide-to="{{ forloop.counter0 }}"
|
||||||
@ -17,8 +17,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="carousel-inner">
|
<div class="carousel-inner">
|
||||||
{% for film in films_preview %}
|
{% for film in films_preview %}
|
||||||
<div class="carousel-item {% if forloop.counter0 == 0 %} active {% endif %}" data-bs-interval="10000">
|
<div class="carousel-item {% if forloop.counter0 == 0 %} active {% endif %}" data-bs-interval="10">
|
||||||
<img src="{{ film.image.url }}" class="d-block w-100 film_card_image" alt="Фотография фильма не найдена">
|
<img src="{{ film.image.url }}" class="d-block w-100 film_preview_image"
|
||||||
|
alt="Фотография фильма не найдена">
|
||||||
<div class="carousel-caption d-none d-md-block caption_block">
|
<div class="carousel-caption d-none d-md-block caption_block">
|
||||||
<h5>{{ film.name }}</h5>
|
<h5>{{ film.name }}</h5>
|
||||||
<p>{{ film.description|truncatewords_html:10|safe }}</p>
|
<p>{{ film.description|truncatewords_html:10|safe }}</p>
|
||||||
@ -36,4 +37,58 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="timetable_block">
|
||||||
|
<h1 class="header_title">Расписание</h1>
|
||||||
|
<div class="container">
|
||||||
|
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||||
|
{% for date in films_sessions %}
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link tab_btn {% if forloop.counter0 == 0 %} active {% endif %}"
|
||||||
|
id="tab-{{ date }}"
|
||||||
|
data-bs-toggle="tab" data-bs-target="#content-{{ date|date:'Y-m-d' }}"
|
||||||
|
type="button" role="tab" aria-controls="content-{{ date|date:'Y-m-d' }}"
|
||||||
|
aria-selected="true">
|
||||||
|
{% if date|date == now|date %}
|
||||||
|
Сегодня
|
||||||
|
{% elif date|date == tomorrow|date %}
|
||||||
|
Завтра
|
||||||
|
{% else %}
|
||||||
|
{{ date|date:"j M" }}
|
||||||
|
{% endif %}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="myTabContent">
|
||||||
|
{% for date, sessions in films_sessions.items %}
|
||||||
|
<div class="tab-pane fade timetable_body {% if forloop.counter0 == 0 %} show active {% endif %}"
|
||||||
|
id="content-{{ date|date:'Y-m-d' }}" role="tabpanel"
|
||||||
|
aria-labelledby="tab-{{ date }}"
|
||||||
|
aria-selected="{% if forloop.counter0 == 0 %} true {% else %} false {% endif %}">
|
||||||
|
{% for film, session in sessions.items %}
|
||||||
|
<div class="film_card">
|
||||||
|
{% if film.image %}
|
||||||
|
<img src="{{ film.image.url }}" class="d-block w-100 film_card_image film_card_item"
|
||||||
|
alt="Фотография фильма не найдена">
|
||||||
|
{% else %}
|
||||||
|
Картинки нет :(
|
||||||
|
{% endif %}
|
||||||
|
<div class="film_card_column">
|
||||||
|
<label class="film_card_column_item">{{film.name}}</label>
|
||||||
|
<div class="film_card_row">
|
||||||
|
{% for time_sessions in session %}
|
||||||
|
<div class="film_session">
|
||||||
|
<a class="session_time">{{ time_sessions.start_datetime|time:"H:i" }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -1,11 +1,27 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.db.models import Model, CharField, IntegerField, CASCADE, DateTimeField, FloatField, ForeignKey
|
from django.db.models import Model, CharField, IntegerField, CASCADE, DateTimeField, FloatField, ForeignKey, Manager
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from films.models import Film
|
from films.models import Film
|
||||||
|
|
||||||
|
|
||||||
|
class FilmSessionsManager(Manager):
|
||||||
|
def nearest_timetable(self):
|
||||||
|
current_datetime = timezone.now()
|
||||||
|
end_datetime = current_datetime + timedelta(days=5)
|
||||||
|
films_sessions = super().get_queryset().filter(
|
||||||
|
start_datetime__gte=current_datetime,
|
||||||
|
start_datetime__lte=end_datetime,
|
||||||
|
).prefetch_related(
|
||||||
|
FilmSession.film.field.name,
|
||||||
|
).order_by(
|
||||||
|
FilmSession.start_datetime.field.name,
|
||||||
|
)
|
||||||
|
return films_sessions
|
||||||
|
|
||||||
|
|
||||||
class Auditorium(Model):
|
class Auditorium(Model):
|
||||||
number = CharField(
|
number = CharField(
|
||||||
max_length=20,
|
max_length=20,
|
||||||
@ -55,6 +71,8 @@ class Row(Model):
|
|||||||
|
|
||||||
|
|
||||||
class FilmSession(Model):
|
class FilmSession(Model):
|
||||||
|
objects = FilmSessionsManager()
|
||||||
|
|
||||||
start_datetime = DateTimeField(
|
start_datetime = DateTimeField(
|
||||||
verbose_name='Дата и время начала сеанса',
|
verbose_name='Дата и время начала сеанса',
|
||||||
)
|
)
|
||||||
@ -65,7 +83,6 @@ class FilmSession(Model):
|
|||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
price = FloatField(
|
price = FloatField(
|
||||||
verbose_name='Цена билета',
|
verbose_name='Цена билета',
|
||||||
validators=[
|
validators=[
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user