сделал процедуру оформления заказа и покупки билетов
This commit is contained in:
parent
72e025bb34
commit
be03d5c234
@ -4,3 +4,4 @@ from django.apps import AppConfig
|
|||||||
class FilmsConfig(AppConfig):
|
class FilmsConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'films'
|
name = 'films'
|
||||||
|
verbose_name = 'Фильмы'
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
# Create your models here.
|
|
||||||
@ -118,3 +118,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.2vw;
|
font-size: 1.2vw;
|
||||||
}
|
}
|
||||||
|
.disabled {
|
||||||
|
background-color: #0d1d3a !important;
|
||||||
|
}
|
||||||
@ -34,11 +34,19 @@
|
|||||||
<td class="row_number_cell cell">Ряд {{ forloop.counter }}</td>
|
<td class="row_number_cell cell">Ряд {{ forloop.counter }}</td>
|
||||||
{% for _ in row.column_count|get_range %}
|
{% for _ in row.column_count|get_range %}
|
||||||
<td class="cell">
|
<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">
|
<label class="film_session">
|
||||||
<input type="checkbox" name="selected_seats"
|
<input type="checkbox" name="selected_seats"
|
||||||
value="[{{ forloop.counter }}, {{ row.row_number }}]" class="seat_checkbox">
|
value="[{{ forloop.counter }}, {{ row.row_number }}]" class="seat_checkbox">
|
||||||
<span class="seat_number">{{ forloop.counter }}</span>
|
<span class="seat_number">{{ forloop.counter }}</span>
|
||||||
</label>
|
</label>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -1,3 +1,18 @@
|
|||||||
from django.contrib import admin
|
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,
|
||||||
|
]
|
||||||
|
|||||||
@ -4,3 +4,4 @@ from django.apps import AppConfig
|
|||||||
class TicketsConfig(AppConfig):
|
class TicketsConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'tickets'
|
name = 'tickets'
|
||||||
|
verbose_name = 'Билеты'
|
||||||
|
|||||||
@ -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="Дата и время оформления заказа",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -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 django.core.validators import MinValueValidator
|
||||||
|
|
||||||
from timetable.models import FilmSession
|
from timetable.models import FilmSession
|
||||||
from users.models import Profile
|
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):
|
class Order(Model):
|
||||||
session = ForeignKey(
|
session = ForeignKey(
|
||||||
FilmSession,
|
FilmSession,
|
||||||
@ -20,7 +26,7 @@ class Order(Model):
|
|||||||
related_query_name='orders',
|
related_query_name='orders',
|
||||||
)
|
)
|
||||||
|
|
||||||
datetime_order = DateField(
|
datetime_order = DateTimeField(
|
||||||
verbose_name='Дата и время оформления заказа',
|
verbose_name='Дата и время оформления заказа',
|
||||||
help_text='Дата и время оформления заказа',
|
help_text='Дата и время оформления заказа',
|
||||||
)
|
)
|
||||||
@ -32,6 +38,8 @@ class Order(Model):
|
|||||||
|
|
||||||
|
|
||||||
class Ticket(Model):
|
class Ticket(Model):
|
||||||
|
objects = TicketManager()
|
||||||
|
|
||||||
order = ForeignKey(
|
order = ForeignKey(
|
||||||
Order,
|
Order,
|
||||||
on_delete=CASCADE,
|
on_delete=CASCADE,
|
||||||
|
|||||||
@ -4,3 +4,4 @@ from django.apps import AppConfig
|
|||||||
class TimetableConfig(AppConfig):
|
class TimetableConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'timetable'
|
name = 'timetable'
|
||||||
|
verbose_name = 'Сеансы и залы'
|
||||||
|
|||||||
@ -24,6 +24,6 @@ class SeatSelectionForm(forms.Form):
|
|||||||
|
|
||||||
def clean_selected_seats(self):
|
def clean_selected_seats(self):
|
||||||
selected_seats = self.cleaned_data['selected_seats']
|
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]
|
selected_seats = [loads(field) for field in selected_seats]
|
||||||
return selected_seats
|
return selected_seats
|
||||||
|
|||||||
@ -112,6 +112,9 @@ class FilmSession(Model):
|
|||||||
related_query_name='sessions',
|
related_query_name='sessions',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.film.name} - {str(self.start_datetime)} - {self.auditorium}'
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
if self.start_datetime and self.film.duration:
|
if self.start_datetime and self.film.duration:
|
||||||
self.end_datetime = self.start_datetime + timedelta(minutes=self.film.duration)
|
self.end_datetime = self.start_datetime + timedelta(minutes=self.film.duration)
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from datetime import date
|
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.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.models import FilmSession, Row
|
||||||
|
|
||||||
from timetable.forms import SeatSelectionForm
|
from timetable.forms import SeatSelectionForm
|
||||||
|
from tickets.models import Order, Ticket
|
||||||
|
|
||||||
|
|
||||||
def timetable_view(request):
|
def timetable_view(request):
|
||||||
@ -42,6 +45,7 @@ def timetable_view(request):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
def session_view(request, sess_id):
|
def session_view(request, sess_id):
|
||||||
session = get_object_or_404(
|
session = get_object_or_404(
|
||||||
FilmSession.objects.all(),
|
FilmSession.objects.all(),
|
||||||
@ -49,11 +53,30 @@ def session_view(request, sess_id):
|
|||||||
)
|
)
|
||||||
height = round(session.auditorium.rows.count() * 4 + 7)
|
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':
|
if request.method == 'POST':
|
||||||
form = SeatSelectionForm(request.POST, auditorium=session.auditorium)
|
form = SeatSelectionForm(request.POST, auditorium=session.auditorium)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
with transaction.atomic():
|
||||||
selected_seats = form.clean_selected_seats()
|
selected_seats = form.clean_selected_seats()
|
||||||
# return redirect('куда-то-перенаправление-после-выбора-мест')
|
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:
|
else:
|
||||||
form = SeatSelectionForm(auditorium=session.auditorium)
|
form = SeatSelectionForm(auditorium=session.auditorium)
|
||||||
|
|
||||||
@ -61,6 +84,7 @@ def session_view(request, sess_id):
|
|||||||
'session': session,
|
'session': session,
|
||||||
'height': height,
|
'height': height,
|
||||||
'form': form,
|
'form': form,
|
||||||
|
'occupied_seats': occupied_seats,
|
||||||
}
|
}
|
||||||
template = 'timetable/session.html'
|
template = 'timetable/session.html'
|
||||||
return render(request, template, context)
|
return render(request, template, context)
|
||||||
|
|||||||
@ -4,3 +4,4 @@ from django.apps import AppConfig
|
|||||||
class UsersConfig(AppConfig):
|
class UsersConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = 'users'
|
name = 'users'
|
||||||
|
verbose_name = 'Пользователи'
|
||||||
|
|||||||
@ -41,6 +41,9 @@ class Profile(Model):
|
|||||||
related_query_name='profiles',
|
related_query_name='profiles',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.user} - {self.user.last_name} {self.user.first_name}'
|
||||||
|
|
||||||
def get_image_x300(self):
|
def get_image_x300(self):
|
||||||
return get_thumbnail(
|
return get_thumbnail(
|
||||||
self.image,
|
self.image,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user