доделал главную страницу
This commit is contained in:
parent
20fe040626
commit
1aa2ea5a9e
@ -1,19 +1,28 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
from films.models import Film, Genre
|
from films.models import Film, Genre
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Film)
|
@admin.register(Film)
|
||||||
class ItemAdmin(admin.ModelAdmin):
|
class FilmAdmin(admin.ModelAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
Film.name.field.name,
|
Film.name.field.name,
|
||||||
Film.duration.field.name,
|
Film.duration.field.name,
|
||||||
|
'get_image',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
readonly_fields = ("get_image",)
|
||||||
|
|
||||||
filter_horizontal = [
|
filter_horizontal = [
|
||||||
Film.genres.field.name,
|
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)
|
@admin.register(Genre)
|
||||||
class GenreAdmin(admin.ModelAdmin):
|
class GenreAdmin(admin.ModelAdmin):
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
import sorl
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Model,
|
Model,
|
||||||
CharField,
|
CharField,
|
||||||
@ -11,6 +12,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 django.utils.safestring import mark_safe
|
||||||
from sorl.thumbnail import get_thumbnail
|
from sorl.thumbnail import get_thumbnail
|
||||||
|
|
||||||
|
|
||||||
@ -47,6 +49,9 @@ class Genre(Model):
|
|||||||
null=False,
|
null=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'films_genres'
|
db_table = 'films_genres'
|
||||||
verbose_name = 'Жанр'
|
verbose_name = 'Жанр'
|
||||||
@ -54,12 +59,12 @@ class Genre(Model):
|
|||||||
|
|
||||||
|
|
||||||
class Film(Model):
|
class Film(Model):
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
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(
|
||||||
@ -102,6 +107,25 @@ class Film(Model):
|
|||||||
help_text='Жанры фильма',
|
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:
|
class Meta:
|
||||||
db_table = 'films_films'
|
db_table = 'films_films'
|
||||||
verbose_name = 'Фильм'
|
verbose_name = 'Фильм'
|
||||||
|
|||||||
@ -1,13 +1,8 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from datetime import date
|
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
|
from timetable.models import FilmSession
|
||||||
|
|
||||||
@ -15,23 +10,31 @@ 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()
|
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:
|
for session in film_sessions:
|
||||||
session_date = session.start_datetime.date()
|
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:
|
for session_date, session_films in sessions_by_date_and_film.items():
|
||||||
session_date = session.start_datetime.date()
|
for session_film in session_films:
|
||||||
sessions_by_date_and_film[session_date] = dict(sessions_by_date_and_film[session_date])
|
sessions_by_date_and_film[session_date][session_film].sort(
|
||||||
|
key=lambda sorted_session: sorted_session.start_datetime,
|
||||||
|
)
|
||||||
|
|
||||||
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),
|
'films_sessions': sessions_by_date_and_film,
|
||||||
'tomorrow': date.today() + datetime.timedelta(days=1)
|
'today': date.today(),
|
||||||
|
'tomorrow': date.today() + datetime.timedelta(days=1),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
|
|||||||
@ -5,7 +5,7 @@ body {
|
|||||||
background-color: #0d1d3a;
|
background-color: #0d1d3a;
|
||||||
}
|
}
|
||||||
html::-webkit-scrollbar {
|
html::-webkit-scrollbar {
|
||||||
width: 0.8vw;
|
width: 4px;
|
||||||
}
|
}
|
||||||
html::-webkit-scrollbar-thumb {
|
html::-webkit-scrollbar-thumb {
|
||||||
background-color: #eaeaea;
|
background-color: #eaeaea;
|
||||||
|
|||||||
@ -71,32 +71,61 @@
|
|||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
height: 10vw;
|
height: 10vw;
|
||||||
margin-left: 2vw;
|
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%;
|
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 {
|
.film_card_row {
|
||||||
height: 80%;
|
height: 60%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
|
.film_card_footer {
|
||||||
|
height: 20%;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
.film_session {
|
.film_session {
|
||||||
display: inline-block;
|
background-color: rgb(255, 64, 96);
|
||||||
background-color: rgb(255, 91, 119);
|
color: #eaeaea;
|
||||||
color: #ffffff;
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 5px;
|
padding: 10px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-bottom: 15px;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
border-radius: 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 {
|
.session_time {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #ffffff;
|
color: #eaeaea;
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
.session_time:hover {
|
.genre {
|
||||||
color: #ffffff;
|
margin-right: 0.5vw;
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
@ -5,9 +5,7 @@
|
|||||||
{% endblock title %}
|
{% endblock title %}
|
||||||
{% 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 id="carouselWhite" class="carousel carousel slide carousel_films" data-bs-ride="carousel">
|
||||||
<h1 class="header_title">Сейчас в прокате</h1>
|
|
||||||
<div id="carouselWhite" class="carousel carousel slide">
|
|
||||||
<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,7 +15,7 @@
|
|||||||
</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="10">
|
<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"
|
<img src="{{ film.image.url }}" class="d-block w-100 film_preview_image"
|
||||||
alt="Фотография фильма не найдена">
|
alt="Фотография фильма не найдена">
|
||||||
<div class="carousel-caption d-none d-md-block caption_block">
|
<div class="carousel-caption d-none d-md-block caption_block">
|
||||||
@ -36,7 +34,6 @@
|
|||||||
<span class="visually-hidden">Next</span>
|
<span class="visually-hidden">Next</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="timetable_block">
|
<div class="timetable_block">
|
||||||
<h1 class="header_title">Расписание</h1>
|
<h1 class="header_title">Расписание</h1>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -48,7 +45,7 @@
|
|||||||
data-bs-toggle="tab" data-bs-target="#content-{{ date|date:'Y-m-d' }}"
|
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' }}"
|
type="button" role="tab" aria-controls="content-{{ date|date:'Y-m-d' }}"
|
||||||
aria-selected="true">
|
aria-selected="true">
|
||||||
{% if date|date == now|date %}
|
{% if date|date == today|date %}
|
||||||
Сегодня
|
Сегодня
|
||||||
{% elif date|date == tomorrow|date %}
|
{% elif date|date == tomorrow|date %}
|
||||||
Завтра
|
Завтра
|
||||||
@ -74,12 +71,19 @@
|
|||||||
Картинки нет :(
|
Картинки нет :(
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="film_card_column">
|
<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">
|
<div class="film_card_row">
|
||||||
{% for time_sessions in session %}
|
{% for time_sessions in session %}
|
||||||
<div class="film_session">
|
<a class="film_session" href="">
|
||||||
<a class="session_time">{{ time_sessions.start_datetime|time:"H:i" }}</a>
|
<div class="session_time">{{ time_sessions.start_datetime|time:"H:i" }}</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="film_card_footer">
|
||||||
|
{% for genre in film.genres.all %}
|
||||||
|
<div class="badge text-bg-secondary genre">{{genre.name}}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<link href="{% static 'css/users/profile.css' %}" rel="stylesheet">
|
<link href="{% static 'css/users/profile.css' %}" rel="stylesheet">
|
||||||
<div class="profile_block">
|
<div class="profile_block">
|
||||||
<h1>{{ user.username }}</h1>
|
<h1>Профиль</h1>
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% if user_form.non_field_errors %}
|
{% if user_form.non_field_errors %}
|
||||||
|
|||||||
@ -1,3 +1,25 @@
|
|||||||
from django.contrib import admin
|
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:
|
class Meta:
|
||||||
db_table = 'timetable_auditoriums'
|
db_table = 'timetable_auditoriums'
|
||||||
verbose_name = 'Зал'
|
verbose_name = 'Зал'
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
from django.urls import path
|
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'
|
app_name = 'time_table'
|
||||||
|
|
||||||
urlpatterns = [
|
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
|
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.birthday.field.name,
|
||||||
model.image.field.name,
|
model.image.field.name,
|
||||||
]
|
]
|
||||||
widgets = {
|
|
||||||
model.birthday.field.name: DateInput(attrs={'type': 'date'})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class CustomUserChangeForm(UserChangeForm):
|
class CustomUserChangeForm(UserChangeForm):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user