доделал главную страницу
This commit is contained in:
parent
20fe040626
commit
1aa2ea5a9e
@ -1,19 +1,28 @@
|
||||
from django.contrib import admin
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from films.models import Film, Genre
|
||||
|
||||
|
||||
@admin.register(Film)
|
||||
class ItemAdmin(admin.ModelAdmin):
|
||||
class FilmAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
Film.name.field.name,
|
||||
Film.duration.field.name,
|
||||
'get_image',
|
||||
]
|
||||
|
||||
readonly_fields = ("get_image",)
|
||||
|
||||
filter_horizontal = [
|
||||
Film.genres.field.name,
|
||||
]
|
||||
|
||||
def get_image(self, obj):
|
||||
return mark_safe(
|
||||
f"<img src='{obj.image_tmb()}' width='50' height='50'",
|
||||
)
|
||||
|
||||
|
||||
@admin.register(Genre)
|
||||
class GenreAdmin(admin.ModelAdmin):
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
import sorl
|
||||
from django.db.models import (
|
||||
Model,
|
||||
CharField,
|
||||
@ -11,6 +12,7 @@ from django.db.models import (
|
||||
)
|
||||
from django.utils import timezone
|
||||
from django.core.validators import MinValueValidator
|
||||
from django.utils.safestring import mark_safe
|
||||
from sorl.thumbnail import get_thumbnail
|
||||
|
||||
|
||||
@ -47,6 +49,9 @@ class Genre(Model):
|
||||
null=False,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
db_table = 'films_genres'
|
||||
verbose_name = 'Жанр'
|
||||
@ -54,12 +59,12 @@ class Genre(Model):
|
||||
|
||||
|
||||
class Film(Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
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(
|
||||
@ -102,6 +107,25 @@ class Film(Model):
|
||||
help_text='Жанры фильма',
|
||||
)
|
||||
|
||||
def get_image_300x300(self):
|
||||
return sorl.thumbnail.get_thumbnail(
|
||||
self.image,
|
||||
"300x300",
|
||||
crop="center",
|
||||
quality=51,
|
||||
)
|
||||
|
||||
def image_tmb(self):
|
||||
if self.image:
|
||||
tag = f"{self.get_image_300x300().url}"
|
||||
return mark_safe(tag)
|
||||
|
||||
return "Нет изорбражения"
|
||||
|
||||
image_tmb.field_name = "image_tmb"
|
||||
image_tmb.allow_tags = True
|
||||
image_tmb.short_description = "Превью"
|
||||
|
||||
class Meta:
|
||||
db_table = 'films_films'
|
||||
verbose_name = 'Фильм'
|
||||
|
||||
@ -1,13 +1,8 @@
|
||||
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
|
||||
|
||||
@ -15,23 +10,31 @@ 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))
|
||||
sessions_by_date_and_film = {}
|
||||
|
||||
for session in film_sessions:
|
||||
session_date = session.start_datetime.date()
|
||||
sessions_by_date_and_film[session_date][session.film].append(session)
|
||||
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 in film_sessions:
|
||||
session_date = session.start_datetime.date()
|
||||
sessions_by_date_and_film[session_date] = dict(sessions_by_date_and_film[session_date])
|
||||
for session_date, session_films in sessions_by_date_and_film.items():
|
||||
for session_film in session_films:
|
||||
sessions_by_date_and_film[session_date][session_film].sort(
|
||||
key=lambda sorted_session: sorted_session.start_datetime,
|
||||
)
|
||||
|
||||
template = render(
|
||||
request,
|
||||
'home/homepage.html',
|
||||
context={
|
||||
'films_preview': films,
|
||||
'films_sessions': dict(sessions_by_date_and_film),
|
||||
'tomorrow': date.today() + datetime.timedelta(days=1)
|
||||
'films_sessions': sessions_by_date_and_film,
|
||||
'today': date.today(),
|
||||
'tomorrow': date.today() + datetime.timedelta(days=1),
|
||||
}
|
||||
)
|
||||
return HttpResponse(
|
||||
|
||||
@ -5,7 +5,7 @@ body {
|
||||
background-color: #0d1d3a;
|
||||
}
|
||||
html::-webkit-scrollbar {
|
||||
width: 0.8vw;
|
||||
width: 4px;
|
||||
}
|
||||
html::-webkit-scrollbar-thumb {
|
||||
background-color: #eaeaea;
|
||||
|
||||
@ -71,32 +71,61 @@
|
||||
justify-content: space-around;
|
||||
height: 10vw;
|
||||
margin-left: 2vw;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.film_card_column_item {
|
||||
.film_card_column::-webkit-scrollbar {
|
||||
height: 7px;
|
||||
}
|
||||
.film_card_column::-webkit-scrollbar-thumb {
|
||||
background-color: #0d1d3a;
|
||||
border-radius: 5vw;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
.film_card_title_row {
|
||||
height: 20%;
|
||||
margin-top: 0.5vw;
|
||||
margin-bottom: 0.5vw;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.film_card_row {
|
||||
height: 80%;
|
||||
height: 60%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.film_card_footer {
|
||||
height: 20%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.film_session {
|
||||
display: inline-block;
|
||||
background-color: rgb(255, 91, 119);
|
||||
color: #ffffff;
|
||||
background-color: rgb(255, 64, 96);
|
||||
color: #eaeaea;
|
||||
font-weight: bold;
|
||||
padding: 5px;
|
||||
padding: 10px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
margin: 5px;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.film_session:hover {
|
||||
background-color: rgb(196, 47, 72);
|
||||
}
|
||||
.session_time {
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
color: #eaeaea;
|
||||
}
|
||||
.session_time:hover {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
.genre {
|
||||
margin-right: 0.5vw;
|
||||
}
|
||||
@ -5,37 +5,34 @@
|
||||
{% endblock title %}
|
||||
{% 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">
|
||||
<div class="carousel-indicators">
|
||||
{% for film in films_preview %}
|
||||
<button type="button" data-bs-target="#carouselWhite" data-bs-slide-to="{{ forloop.counter0 }}"
|
||||
class="{% if forloop.counter0 == 0 %} active {% endif %}"
|
||||
aria-current="true" aria-label="{{film.name|truncatewords_html:5}}"></button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="carousel-inner">
|
||||
{% for film in films_preview %}
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button class="carousel-control-prev" type="button" data-bs-target="#carouselWhite" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</button>
|
||||
<button class="carousel-control-next" type="button" data-bs-target="#carouselWhite" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</button>
|
||||
<div id="carouselWhite" class="carousel carousel slide carousel_films" data-bs-ride="carousel">
|
||||
<div class="carousel-indicators">
|
||||
{% for film in films_preview %}
|
||||
<button type="button" data-bs-target="#carouselWhite" data-bs-slide-to="{{ forloop.counter0 }}"
|
||||
class="{% if forloop.counter0 == 0 %} active {% endif %}"
|
||||
aria-current="true" aria-label="{{film.name|truncatewords_html:5}}"></button>
|
||||
{% endfor %}
|
||||
</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_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>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button class="carousel-control-prev" type="button" data-bs-target="#carouselWhite" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</button>
|
||||
<button class="carousel-control-next" type="button" data-bs-target="#carouselWhite" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="visually-hidden">Next</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="timetable_block">
|
||||
<h1 class="header_title">Расписание</h1>
|
||||
@ -48,7 +45,7 @@
|
||||
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 %}
|
||||
{% if date|date == today|date %}
|
||||
Сегодня
|
||||
{% elif date|date == tomorrow|date %}
|
||||
Завтра
|
||||
@ -74,12 +71,19 @@
|
||||
Картинки нет :(
|
||||
{% endif %}
|
||||
<div class="film_card_column">
|
||||
<label class="film_card_column_item">{{film.name}}</label>
|
||||
<div class="film_card_title_row">
|
||||
<label>{{film.name}}</label>
|
||||
</div>
|
||||
<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>
|
||||
<a class="film_session" href="">
|
||||
<div class="session_time">{{ time_sessions.start_datetime|time:"H:i" }}</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="film_card_footer">
|
||||
{% for genre in film.genres.all %}
|
||||
<div class="badge text-bg-secondary genre">{{genre.name}}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
{% block content %}
|
||||
<link href="{% static 'css/users/profile.css' %}" rel="stylesheet">
|
||||
<div class="profile_block">
|
||||
<h1>{{ user.username }}</h1>
|
||||
<h1>Профиль</h1>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% if user_form.non_field_errors %}
|
||||
|
||||
@ -1,3 +1,25 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
from timetable.models import Auditorium, Row, FilmSession
|
||||
|
||||
|
||||
@admin.register(Auditorium)
|
||||
class AuditoriumAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
Auditorium.number.field.name,
|
||||
]
|
||||
|
||||
|
||||
@admin.register(Row)
|
||||
class RowAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
Row.row_number.field.name,
|
||||
]
|
||||
|
||||
|
||||
@admin.register(FilmSession)
|
||||
class FilmSessionAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
FilmSession.start_datetime.field.name,
|
||||
FilmSession.film.field.name,
|
||||
]
|
||||
|
||||
@ -35,6 +35,9 @@ class Auditorium(Model):
|
||||
],
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.number
|
||||
|
||||
class Meta:
|
||||
db_table = 'timetable_auditoriums'
|
||||
verbose_name = 'Зал'
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
from django.urls import path
|
||||
|
||||
from films.views import films_list, film_details
|
||||
from timetable.views import timetable_view, session_view
|
||||
|
||||
app_name = 'time_table'
|
||||
|
||||
urlpatterns = [
|
||||
path('', films_list, name='main'),
|
||||
path('', timetable_view, name='main'),
|
||||
path('session/<int:pk>', session_view, name='main'),
|
||||
]
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
|
||||
def timetable_view(request):
|
||||
pass
|
||||
|
||||
|
||||
def session_view(request):
|
||||
pass
|
||||
|
||||
@ -77,9 +77,6 @@ class ProfileForm(forms.ModelForm):
|
||||
model.birthday.field.name,
|
||||
model.image.field.name,
|
||||
]
|
||||
widgets = {
|
||||
model.birthday.field.name: DateInput(attrs={'type': 'date'})
|
||||
}
|
||||
|
||||
|
||||
class CustomUserChangeForm(UserChangeForm):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user