forked from CGM_Public/pretix_original
Add SubEvent.last_modified
This commit is contained in:
@@ -51,6 +51,7 @@ seating_plan integer If reserved sea
|
|||||||
plan. Otherwise ``null``.
|
plan. Otherwise ``null``.
|
||||||
seat_category_mapping object An object mapping categories of the seating plan
|
seat_category_mapping object An object mapping categories of the seating plan
|
||||||
(strings) to items in the event (integers or ``null``).
|
(strings) to items in the event (integers or ``null``).
|
||||||
|
last_modified datetime Last modification of this object
|
||||||
===================================== ========================== =======================================================
|
===================================== ========================== =======================================================
|
||||||
|
|
||||||
.. versionchanged:: 1.7
|
.. versionchanged:: 1.7
|
||||||
@@ -80,6 +81,10 @@ seat_category_mapping object An object mappi
|
|||||||
|
|
||||||
The ``disabled`` attribute has been added to ``item_price_overrides`` and ``variation_price_overrides``.
|
The ``disabled`` attribute has been added to ``item_price_overrides`` and ``variation_price_overrides``.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.12
|
||||||
|
|
||||||
|
The ``last_modified`` attribute has been added.
|
||||||
|
|
||||||
Endpoints
|
Endpoints
|
||||||
---------
|
---------
|
||||||
|
|
||||||
@@ -148,6 +153,8 @@ Endpoints
|
|||||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
||||||
:param organizer: The ``slug`` field of a valid organizer
|
:param organizer: The ``slug`` field of a valid organizer
|
||||||
:param event: The ``slug`` field of the main event
|
:param event: The ``slug`` field of the main event
|
||||||
|
:query datetime modified_since: Only return objects that have changed since the given date. Be careful: This does not
|
||||||
|
allow you to know if a subevent was deleted.
|
||||||
:query array attr[meta_data_key]: By providing the key and value of a meta data attribute, the list of sub-events
|
:query array attr[meta_data_key]: By providing the key and value of a meta data attribute, the list of sub-events
|
||||||
will only contain the sub-events matching the set criteria. Providing ``?attr[Format]=Seminar`` would return
|
will only contain the sub-events matching the set criteria. Providing ``?attr[Format]=Seminar`` would return
|
||||||
only those sub-events having set their ``Format`` meta data to ``Seminar``, ``?attr[Format]=`` only those, that
|
only those sub-events having set their ``Format`` meta data to ``Seminar``, ``?attr[Format]=`` only those, that
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ class SubEventSerializer(I18nAwareModelSerializer):
|
|||||||
fields = ('id', 'name', 'date_from', 'date_to', 'active', 'date_admission',
|
fields = ('id', 'name', 'date_from', 'date_to', 'active', 'date_admission',
|
||||||
'presale_start', 'presale_end', 'location', 'geo_lat', 'geo_lon', 'event', 'is_public',
|
'presale_start', 'presale_end', 'location', 'geo_lat', 'geo_lon', 'event', 'is_public',
|
||||||
'seating_plan', 'item_price_overrides', 'variation_price_overrides', 'meta_data',
|
'seating_plan', 'item_price_overrides', 'variation_price_overrides', 'meta_data',
|
||||||
'seat_category_mapping')
|
'seat_category_mapping', 'last_modified')
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
data = super().validate(data)
|
data = super().validate(data)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from django.db.models import ProtectedError, Q
|
|||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
from rest_framework import filters, views, viewsets
|
from rest_framework import filters, serializers, views, viewsets
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
@@ -194,6 +194,7 @@ with scopes_disabled():
|
|||||||
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
|
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
|
||||||
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
|
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
|
||||||
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
|
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
|
||||||
|
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
@@ -233,6 +234,8 @@ class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
|
|||||||
write_permission = 'can_change_event_settings'
|
write_permission = 'can_change_event_settings'
|
||||||
filter_backends = (DjangoFilterBackend, filters.OrderingFilter)
|
filter_backends = (DjangoFilterBackend, filters.OrderingFilter)
|
||||||
filterset_class = SubEventFilter
|
filterset_class = SubEventFilter
|
||||||
|
ordering = ('date_from',)
|
||||||
|
ordering_fields = ('id', 'date_from', 'last_modified')
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
if getattr(self.request, 'event', None):
|
if getattr(self.request, 'event', None):
|
||||||
@@ -254,6 +257,20 @@ class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
|
|||||||
'subeventitem_set', 'subeventitemvariation_set', 'seat_category_mappings'
|
'subeventitem_set', 'subeventitemvariation_set', 'seat_category_mappings'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def list(self, request, **kwargs):
|
||||||
|
date = serializers.DateTimeField().to_representation(now())
|
||||||
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
serializer = self.get_serializer(page, many=True)
|
||||||
|
resp = self.get_paginated_response(serializer.data)
|
||||||
|
resp['X-Page-Generated'] = date
|
||||||
|
return resp
|
||||||
|
|
||||||
|
serializer = self.get_serializer(queryset, many=True)
|
||||||
|
return Response(serializer.data, headers={'X-Page-Generated': date})
|
||||||
|
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
original_data = self.get_serializer(instance=serializer.instance).data
|
original_data = self.get_serializer(instance=serializer.instance).data
|
||||||
super().perform_update(serializer)
|
super().perform_update(serializer)
|
||||||
|
|||||||
18
src/pretix/base/migrations/0164_subevent_last_modified.py
Normal file
18
src/pretix/base/migrations/0164_subevent_last_modified.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.9 on 2020-10-15 16:12
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('pretixbase', '0163_device_security_profile'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='subevent',
|
||||||
|
name='last_modified',
|
||||||
|
field=models.DateTimeField(auto_now=True, db_index=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1036,6 +1036,9 @@ class SubEvent(EventMixin, LoggedModel):
|
|||||||
)
|
)
|
||||||
seating_plan = models.ForeignKey('SeatingPlan', on_delete=models.PROTECT, null=True, blank=True,
|
seating_plan = models.ForeignKey('SeatingPlan', on_delete=models.PROTECT, null=True, blank=True,
|
||||||
related_name='subevents')
|
related_name='subevents')
|
||||||
|
last_modified = models.DateTimeField(
|
||||||
|
auto_now=True, db_index=True
|
||||||
|
)
|
||||||
|
|
||||||
items = models.ManyToManyField('Item', through='SubEventItem')
|
items = models.ManyToManyField('Item', through='SubEventItem')
|
||||||
variations = models.ManyToManyField('ItemVariation', through='SubEventItemVariation')
|
variations = models.ManyToManyField('ItemVariation', through='SubEventItemVariation')
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ from i18nfield.strings import LazyI18nString
|
|||||||
from pretix.base.channels import get_all_sales_channels
|
from pretix.base.channels import get_all_sales_channels
|
||||||
from pretix.base.forms.questions import guess_country
|
from pretix.base.forms.questions import guess_country
|
||||||
from pretix.base.models import (
|
from pretix.base.models import (
|
||||||
ItemVariation, OrderPosition, QuestionAnswer, QuestionOption, Seat,
|
ItemVariation, OrderPosition, Question, QuestionAnswer, QuestionOption,
|
||||||
Question)
|
Seat,
|
||||||
|
)
|
||||||
from pretix.base.services.pricing import get_price
|
from pretix.base.services.pricing import get_price
|
||||||
from pretix.base.settings import (
|
from pretix.base.settings import (
|
||||||
COUNTRIES_WITH_STATE_IN_ADDRESS, PERSON_NAME_SCHEMES,
|
COUNTRIES_WITH_STATE_IN_ADDRESS, PERSON_NAME_SCHEMES,
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ def item2(event2):
|
|||||||
def test_subevent_list(token_client, organizer, event, subevent):
|
def test_subevent_list(token_client, organizer, event, subevent):
|
||||||
res = dict(TEST_SUBEVENT_RES)
|
res = dict(TEST_SUBEVENT_RES)
|
||||||
res["id"] = subevent.pk
|
res["id"] = subevent.pk
|
||||||
|
res["last_modified"] = subevent.last_modified.isoformat().replace('+00:00', 'Z')
|
||||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug))
|
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug))
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert [res] == resp.data['results']
|
assert [res] == resp.data['results']
|
||||||
@@ -141,16 +142,6 @@ def test_subevent_list_filter(token_client, organizer, event, subevent):
|
|||||||
assert resp.data['count'] == 0
|
assert resp.data['count'] == 0
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
|
||||||
def test_subevent_get(token_client, organizer, event, subevent):
|
|
||||||
res = dict(TEST_SUBEVENT_RES)
|
|
||||||
res["id"] = subevent.pk
|
|
||||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
|
|
||||||
subevent.pk))
|
|
||||||
assert resp.status_code == 200
|
|
||||||
assert res == resp.data
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_subevent_create(token_client, organizer, event, subevent, meta_prop, item):
|
def test_subevent_create(token_client, organizer, event, subevent, meta_prop, item):
|
||||||
resp = token_client.post(
|
resp = token_client.post(
|
||||||
@@ -597,6 +588,7 @@ def test_subevent_update_keep_subeventitems(token_client, organizer, event, sube
|
|||||||
def test_subevent_detail(token_client, organizer, event, subevent):
|
def test_subevent_detail(token_client, organizer, event, subevent):
|
||||||
res = dict(TEST_SUBEVENT_RES)
|
res = dict(TEST_SUBEVENT_RES)
|
||||||
res["id"] = subevent.pk
|
res["id"] = subevent.pk
|
||||||
|
res["last_modified"] = subevent.last_modified.isoformat().replace('+00:00', 'Z')
|
||||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
|
resp = token_client.get('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
|
||||||
subevent.pk))
|
subevent.pk))
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
|
|||||||
Reference in New Issue
Block a user