сделал главную страничку
This commit is contained in:
parent
409d81b82f
commit
4f9b2e2d2b
@ -1,6 +1,5 @@
|
||||
import time
|
||||
from datetime import timedelta
|
||||
from random import shuffle
|
||||
|
||||
from django.db.models import (
|
||||
Model,
|
||||
@ -12,6 +11,7 @@ from django.db.models import (
|
||||
)
|
||||
from django.utils import timezone
|
||||
from django.core.validators import MinValueValidator
|
||||
from sorl.thumbnail import get_thumbnail
|
||||
|
||||
|
||||
class FilmManager(Manager):
|
||||
@ -23,11 +23,19 @@ class FilmManager(Manager):
|
||||
def on_main(self):
|
||||
current_datetime = timezone.now()
|
||||
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__lte=end_datetime,
|
||||
).exclude(image=None).distinct()
|
||||
shuffle(list(films_with_sessions))
|
||||
).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()]
|
||||
return films_with_sessions
|
||||
|
||||
|
||||
@ -49,6 +57,9 @@ class Film(Model):
|
||||
def get_upload_path(self, filename):
|
||||
return f'users/films/{self.pk}/{time.time()}_{filename}'
|
||||
|
||||
def get_image_url(self):
|
||||
return self.image.url
|
||||
|
||||
objects = FilmManager()
|
||||
|
||||
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.shortcuts import render
|
||||
|
||||
from films.models import Film
|
||||
from timetable.models import FilmSession
|
||||
|
||||
|
||||
def homepage(request):
|
||||
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(
|
||||
request,
|
||||
'home/homepage.html',
|
||||
context={
|
||||
'films_preview': films
|
||||
'films_preview': films,
|
||||
'films_sessions': dict(sessions_by_date_and_film),
|
||||
'tomorrow': date.today() + datetime.timedelta(days=1)
|
||||
}
|
||||
)
|
||||
return HttpResponse(
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
height: 30vw;
|
||||
width: 100%;
|
||||
}
|
||||
.film_card_image {
|
||||
.film_preview_image {
|
||||
object-fit: cover;
|
||||
height: 30vw !important;
|
||||
width: 70% !important;
|
||||
@ -22,3 +22,81 @@
|
||||
align-items: center;
|
||||
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 {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
}
|
||||
.nav-item {
|
||||
margin: 5px;
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
{% block content %}
|
||||
<link href="{% static 'css/home/homepage.css' %}" rel="stylesheet">
|
||||
<div class="carousel_films">
|
||||
<h1 class="header_title">Сейчас в прокате</h1>
|
||||
<div id="carouselWhite" class="carousel carousel slide">
|
||||
{{films}}
|
||||
<div class="carousel-indicators">
|
||||
{% for film in films_preview %}
|
||||
<button type="button" data-bs-target="#carouselWhite" data-bs-slide-to="{{ forloop.counter0 }}"
|
||||
@ -17,8 +17,9 @@
|
||||
</div>
|
||||
<div class="carousel-inner">
|
||||
{% for film in films_preview %}
|
||||
<div class="carousel-item {% if forloop.counter0 == 0 %} active {% endif %}" data-bs-interval="10000">
|
||||
<img src="{{ film.image.url }}" class="d-block w-100 film_card_image" alt="Фотография фильма не найдена">
|
||||
<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_preview_image"
|
||||
alt="Фотография фильма не найдена">
|
||||
<div class="carousel-caption d-none d-md-block caption_block">
|
||||
<h5>{{ film.name }}</h5>
|
||||
<p>{{ film.description|truncatewords_html:10|safe }}</p>
|
||||
@ -36,4 +37,58 @@
|
||||
</button>
|
||||
</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 %}
|
||||
@ -1,11 +1,27 @@
|
||||
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.utils import timezone
|
||||
|
||||
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):
|
||||
number = CharField(
|
||||
max_length=20,
|
||||
@ -55,6 +71,8 @@ class Row(Model):
|
||||
|
||||
|
||||
class FilmSession(Model):
|
||||
objects = FilmSessionsManager()
|
||||
|
||||
start_datetime = DateTimeField(
|
||||
verbose_name='Дата и время начала сеанса',
|
||||
)
|
||||
@ -65,7 +83,6 @@ class FilmSession(Model):
|
||||
null=True,
|
||||
)
|
||||
|
||||
|
||||
price = FloatField(
|
||||
verbose_name='Цена билета',
|
||||
validators=[
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user