сделал главную страничку

This commit is contained in:
Андрей Дувакин 2024-04-18 00:18:53 +05:00
parent 409d81b82f
commit 4f9b2e2d2b
6 changed files with 194 additions and 11 deletions

View File

@ -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(

View File

@ -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(

View File

@ -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;
@ -22,3 +22,81 @@
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;
}

View File

@ -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;

View File

@ -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 %}

View File

@ -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=[