сделал процедуру оформления заказа и покупки билетов

This commit is contained in:
Андрей Дувакин 2024-04-21 09:08:42 +05:00
parent 72e025bb34
commit be03d5c234
14 changed files with 98 additions and 12 deletions

View File

@ -4,3 +4,4 @@ from django.apps import AppConfig
class FilmsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'films'
verbose_name = 'Фильмы'

View File

@ -1,3 +0,0 @@
from django.db import models
# Create your models here.

View File

@ -117,4 +117,7 @@
width: 100%;
text-align: center;
font-size: 1.2vw;
}
.disabled {
background-color: #0d1d3a !important;
}

View File

@ -34,11 +34,19 @@
<td class="row_number_cell cell">Ряд {{ forloop.counter }}</td>
{% for _ in row.column_count|get_range %}
<td class="cell">
<label class="film_session disabled">
<input type="checkbox" name="selected_seats"
value="[{{ forloop.counter }}, {{ row.row_number }}]" class="seat_checkbox"
disabled>
<span class="seat_number">{{ forloop.counter }}</span>
</label>
{% else %}
<label class="film_session">
<input type="checkbox" name="selected_seats"
value="[{{ forloop.counter }}, {{ row.row_number }}]" class="seat_checkbox">
<span class="seat_number">{{ forloop.counter }}</span>
</label>
{% endif %}
</td>
{% endfor %}
</tr>

View File

@ -1,3 +1,18 @@
from django.contrib import admin
# Register your models here.
from tickets.models import Ticket, Order
class TicketAdminInline(admin.StackedInline):
model = Ticket
@admin.register(Order)
class AuditoriumAdmin(admin.ModelAdmin):
list_display = [
Order.profile.field.name,
Order.datetime_order.field.name,
]
inlines = [
TicketAdminInline,
]

View File

@ -4,3 +4,4 @@ from django.apps import AppConfig
class TicketsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'tickets'
verbose_name = 'Билеты'

View File

@ -0,0 +1,21 @@
# Generated by Django 4.2 on 2024-04-20 18:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("tickets", "0006_remove_ticket_profile_remove_ticket_session_and_more"),
]
operations = [
migrations.AlterField(
model_name="order",
name="datetime_order",
field=models.DateTimeField(
help_text="Дата и время оформления заказа",
verbose_name="Дата и время оформления заказа",
),
),
]

View File

@ -1,10 +1,16 @@
from django.db.models import ForeignKey, CASCADE, Model, IntegerField, DateField
from django.db.models import ForeignKey, CASCADE, Model, IntegerField, DateTimeField, Manager
from django.core.validators import MinValueValidator
from timetable.models import FilmSession
from users.models import Profile
class TicketManager(Manager):
def get_tickets_for_session(self, session_id):
tickets = super().get_queryset().filter(order__session_id=session_id)
return tickets
class Order(Model):
session = ForeignKey(
FilmSession,
@ -20,7 +26,7 @@ class Order(Model):
related_query_name='orders',
)
datetime_order = DateField(
datetime_order = DateTimeField(
verbose_name='Дата и время оформления заказа',
help_text='Дата и время оформления заказа',
)
@ -32,6 +38,8 @@ class Order(Model):
class Ticket(Model):
objects = TicketManager()
order = ForeignKey(
Order,
on_delete=CASCADE,

View File

@ -4,3 +4,4 @@ from django.apps import AppConfig
class TimetableConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'timetable'
verbose_name = 'Сеансы и залы'

View File

@ -24,6 +24,6 @@ class SeatSelectionForm(forms.Form):
def clean_selected_seats(self):
selected_seats = self.cleaned_data['selected_seats']
if list[str] is type(self.cleaned_data):
if isinstance(selected_seats, list) and all(isinstance(item, str) for item in selected_seats):
selected_seats = [loads(field) for field in selected_seats]
return selected_seats

View File

@ -112,6 +112,9 @@ class FilmSession(Model):
related_query_name='sessions',
)
def __str__(self):
return f'{self.film.name} - {str(self.start_datetime)} - {self.auditorium}'
def save(self, *args, **kwargs):
if self.start_datetime and self.film.duration:
self.end_datetime = self.start_datetime + timedelta(minutes=self.film.duration)

View File

@ -1,13 +1,16 @@
import datetime
from datetime import date
from django.db.models import Max
from django.contrib.auth.decorators import login_required
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse
from django.utils import timezone
from timetable.models import FilmSession, Row
from timetable.forms import SeatSelectionForm
from tickets.models import Order, Ticket
def timetable_view(request):
@ -42,6 +45,7 @@ def timetable_view(request):
)
@login_required
def session_view(request, sess_id):
session = get_object_or_404(
FilmSession.objects.all(),
@ -49,11 +53,30 @@ def session_view(request, sess_id):
)
height = round(session.auditorium.rows.count() * 4 + 7)
tickets = Ticket.objects.get_tickets_for_session(session.pk)
occupied_seats = [f'{str(ticket.column_number)}{str(ticket.row_number)}' for ticket in tickets]
if request.method == 'POST':
form = SeatSelectionForm(request.POST, auditorium=session.auditorium)
if form.is_valid():
selected_seats = form.clean_selected_seats()
# return redirect('куда-то-перенаправление-после-выбора-мест')
with transaction.atomic():
selected_seats = form.clean_selected_seats()
user_profile = request.user.profile
order = Order.objects.create(
session=session,
profile=user_profile,
datetime_order=timezone.now(),
)
for seat in selected_seats:
Ticket.objects.create(
order=order,
row_number=seat[0],
column_number=seat[1],
)
return redirect(reverse('home:homepage'))
else:
form = SeatSelectionForm(auditorium=session.auditorium)
@ -61,6 +84,7 @@ def session_view(request, sess_id):
'session': session,
'height': height,
'form': form,
'occupied_seats': occupied_seats,
}
template = 'timetable/session.html'
return render(request, template, context)

View File

@ -4,3 +4,4 @@ from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'users'
verbose_name = 'Пользователи'

View File

@ -41,6 +41,9 @@ class Profile(Model):
related_query_name='profiles',
)
def __str__(self):
return f'{self.user} - {self.user.last_name} {self.user.first_name}'
def get_image_x300(self):
return get_thumbnail(
self.image,