начал делать главную страницу, сделал админку для фильмов и жанров, поправил хеадер
This commit is contained in:
parent
50d00cecba
commit
409d81b82f
@ -1,24 +1,22 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
from django.contrib.auth.admin import UserAdmin
|
|
||||||
|
|
||||||
from users.models import Profile
|
from films.models import Film, Genre
|
||||||
|
|
||||||
user = get_user_model()
|
|
||||||
admin.site.unregister(user)
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileInline(admin.TabularInline):
|
@admin.register(Film)
|
||||||
can_delete = False
|
class ItemAdmin(admin.ModelAdmin):
|
||||||
model = Profile
|
list_display = [
|
||||||
fields = [
|
Film.name.field.name,
|
||||||
Profile.birthday.field.name,
|
Film.duration.field.name,
|
||||||
Profile.image.field.name,
|
]
|
||||||
|
|
||||||
|
filter_horizontal = [
|
||||||
|
Film.genres.field.name,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(user)
|
@admin.register(Genre)
|
||||||
class UserAdmin(UserAdmin):
|
class GenreAdmin(admin.ModelAdmin):
|
||||||
inlines = [
|
list_display = [
|
||||||
ProfileInline,
|
Genre.name.field.name,
|
||||||
]
|
]
|
||||||
|
|||||||
24
CineSync/films/migrations/0004_film_image.py
Normal file
24
CineSync/films/migrations/0004_film_image.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 4.2 on 2024-04-17 13:08
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import films.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("films", "0003_film_description"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="film",
|
||||||
|
name="image",
|
||||||
|
field=models.ImageField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
upload_to=films.models.Film.get_upload_path,
|
||||||
|
verbose_name="Изображение фильма",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -1,4 +1,6 @@
|
|||||||
import time
|
import time
|
||||||
|
from datetime import timedelta
|
||||||
|
from random import shuffle
|
||||||
|
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
Model,
|
Model,
|
||||||
@ -18,6 +20,16 @@ class FilmManager(Manager):
|
|||||||
release_date__lt=timezone.now(),
|
release_date__lt=timezone.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def on_main(self):
|
||||||
|
current_datetime = timezone.now()
|
||||||
|
end_datetime = current_datetime + timedelta(days=5)
|
||||||
|
films_with_sessions = Film.objects.filter(
|
||||||
|
sessions__start_datetime__gte=current_datetime,
|
||||||
|
sessions__start_datetime__lte=end_datetime,
|
||||||
|
).exclude(image=None).distinct()
|
||||||
|
shuffle(list(films_with_sessions))
|
||||||
|
return films_with_sessions
|
||||||
|
|
||||||
|
|
||||||
class Genre(Model):
|
class Genre(Model):
|
||||||
name = CharField(
|
name = CharField(
|
||||||
@ -35,7 +47,7 @@ class Genre(Model):
|
|||||||
|
|
||||||
class Film(Model):
|
class Film(Model):
|
||||||
def get_upload_path(self, filename):
|
def get_upload_path(self, filename):
|
||||||
return f'users/avatars/{self.pk}/{time.time()}_{filename}'
|
return f'users/films/{self.pk}/{time.time()}_{filename}'
|
||||||
|
|
||||||
objects = FilmManager()
|
objects = FilmManager()
|
||||||
|
|
||||||
@ -67,7 +79,7 @@ class Film(Model):
|
|||||||
image = ImageField(
|
image = ImageField(
|
||||||
null=True,
|
null=True,
|
||||||
blank=True,
|
blank=True,
|
||||||
verbose_name='Аватар пользователя',
|
verbose_name='Изображение фильма',
|
||||||
upload_to=get_upload_path,
|
upload_to=get_upload_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
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
|
||||||
|
|
||||||
|
|
||||||
def homepage(request):
|
def homepage(request):
|
||||||
|
films = Film.objects.on_main()
|
||||||
template = render(
|
template = render(
|
||||||
request,
|
request,
|
||||||
'home/homepage.html'
|
'home/homepage.html',
|
||||||
|
context={
|
||||||
|
'films_preview': films
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
template,
|
template,
|
||||||
|
|||||||
24
CineSync/static/css/home/homepage.css
Normal file
24
CineSync/static/css/home/homepage.css
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
.carousel_films {
|
||||||
|
margin-top: 5vw;
|
||||||
|
height: 30vw;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.film_card_image {
|
||||||
|
object-fit: cover;
|
||||||
|
height: 30vw !important;
|
||||||
|
width: 70% !important;
|
||||||
|
border-radius: 3vw;
|
||||||
|
}
|
||||||
|
.carousel-item-next, .carousel-item-prev, .carousel-item.active {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.caption_block {
|
||||||
|
background-color: rgba(13, 39, 58, 0.8);
|
||||||
|
border-radius: 2vw;
|
||||||
|
width: 40%;
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 15%;
|
||||||
|
}
|
||||||
@ -4,5 +4,36 @@
|
|||||||
Главная
|
Главная
|
||||||
{% endblock title %}
|
{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<link href="{% static 'css/home/homepage.css' %}" rel="stylesheet">
|
||||||
|
<div class="carousel_films">
|
||||||
|
<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 }}"
|
||||||
|
class="active"
|
||||||
|
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_card_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>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -30,6 +30,9 @@
|
|||||||
<img src="{% static 'img/user.png' %}" class="header_icon col-4">
|
<img src="{% static 'img/user.png' %}" class="header_icon col-4">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
|
{% if user.is_staff %}
|
||||||
|
<a class="btn btn-primary" href="/admin">Админка</a>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 4.2 on 2024-04-17 14:36
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("timetable", "0004_alter_row_auditorium"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="filmsession",
|
||||||
|
name="end_datetime",
|
||||||
|
field=models.DateTimeField(
|
||||||
|
blank=True, null=True, verbose_name="Дата и время начала сеанса"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -1,5 +1,6 @@
|
|||||||
from django.db.models import Model, CharField, IntegerField, OneToOneField, CASCADE, DateTimeField, FloatField, \
|
from datetime import timedelta
|
||||||
ForeignKey
|
|
||||||
|
from django.db.models import Model, CharField, IntegerField, CASCADE, DateTimeField, FloatField, ForeignKey
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
|
|
||||||
from films.models import Film
|
from films.models import Film
|
||||||
@ -58,6 +59,13 @@ class FilmSession(Model):
|
|||||||
verbose_name='Дата и время начала сеанса',
|
verbose_name='Дата и время начала сеанса',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
end_datetime = DateTimeField(
|
||||||
|
verbose_name='Дата и время начала сеанса',
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
price = FloatField(
|
price = FloatField(
|
||||||
verbose_name='Цена билета',
|
verbose_name='Цена билета',
|
||||||
validators=[
|
validators=[
|
||||||
@ -72,7 +80,6 @@ class FilmSession(Model):
|
|||||||
related_name='sessions',
|
related_name='sessions',
|
||||||
related_query_name='sessions',
|
related_query_name='sessions',
|
||||||
)
|
)
|
||||||
|
|
||||||
auditorium = ForeignKey(
|
auditorium = ForeignKey(
|
||||||
Auditorium,
|
Auditorium,
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
@ -81,6 +88,11 @@ class FilmSession(Model):
|
|||||||
related_query_name='sessions',
|
related_query_name='sessions',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.start_datetime and self.film.duration:
|
||||||
|
self.end_datetime = self.start_datetime + timedelta(minutes=self.film.duration)
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'timetable_film_sessions'
|
db_table = 'timetable_film_sessions'
|
||||||
verbose_name = 'Сеанс'
|
verbose_name = 'Сеанс'
|
||||||
|
|||||||
@ -1,3 +1,24 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.auth.admin import UserAdmin
|
||||||
|
|
||||||
# Register your models here.
|
from users.models import Profile
|
||||||
|
|
||||||
|
user = get_user_model()
|
||||||
|
admin.site.unregister(user)
|
||||||
|
|
||||||
|
|
||||||
|
class ProfileInline(admin.TabularInline):
|
||||||
|
can_delete = False
|
||||||
|
model = Profile
|
||||||
|
fields = [
|
||||||
|
Profile.birthday.field.name,
|
||||||
|
Profile.image.field.name,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(user)
|
||||||
|
class UserAdmin(UserAdmin):
|
||||||
|
inlines = [
|
||||||
|
ProfileInline,
|
||||||
|
]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user