From db67959abf803b0b687becaeacf6829de32fa7e2 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Fri, 19 May 2017 10:31:02 +0200 Subject: [PATCH] Add a custom manager --- src/make_testdata.py | 4 +-- src/pretix/base/models/base.py | 38 +++++++++++++++++++-- src/pretix/base/models/event.py | 4 +-- src/pretix/base/models/items.py | 6 ++-- src/pretix/plugins/sendmail/views.py | 1 + src/pretix/plugins/ticketoutputpdf/views.py | 1 + src/tests/base/test_i18n.py | 21 ++++++------ src/tests/base/test_models.py | 4 +-- src/tests/control/test_checkins.py | 4 +-- src/tests/control/test_items.py | 14 ++++---- src/tests/control/test_views.py | 2 +- src/tests/plugins/paypal/test_checkout.py | 2 +- src/tests/plugins/stripe/test_checkout.py | 2 +- src/tests/plugins/test_sendmail.py | 2 +- src/tests/presale/test_cart.py | 4 +-- src/tests/presale/test_checkout.py | 4 +-- src/tests/presale/test_event.py | 12 +++---- src/tests/presale/test_orders.py | 2 +- 18 files changed, 83 insertions(+), 44 deletions(-) diff --git a/src/make_testdata.py b/src/make_testdata.py index 580168b80..dd4528ff9 100644 --- a/src/make_testdata.py +++ b/src/make_testdata.py @@ -37,10 +37,10 @@ t = Team.objects.get_or_create( can_view_orders=True, can_change_orders=True, can_view_vouchers=True, can_change_vouchers=True ) t.members.add(user) -cat_tickets = ItemCategory.objects.create( +cat_tickets = ItemCategory.all.create( event=event, name='Tickets' ) -cat_merch = ItemCategory.objects.create( +cat_merch = ItemCategory.all.create( event=event, name='Merchandise' ) question = Question.objects.create( diff --git a/src/pretix/base/models/base.py b/src/pretix/base/models/base.py index fc40dcfea..9f513eb63 100644 --- a/src/pretix/base/models/base.py +++ b/src/pretix/base/models/base.py @@ -2,6 +2,7 @@ import json import uuid from django.contrib.contenttypes.models import ContentType +from django.core import checks from django.db import models from django.db.models.signals import post_delete from django.dispatch import receiver @@ -34,7 +35,6 @@ def cached_file_delete(sender, instance, **kwargs): class LoggingMixin: - def log_action(self, action, data=None, user=None): """ Create a LogEntry object that is related to this object. @@ -59,7 +59,6 @@ class LoggingMixin: class LoggedModel(models.Model, LoggingMixin): - class Meta: abstract = True @@ -74,3 +73,38 @@ class LoggedModel(models.Model, LoggingMixin): return LogEntry.objects.filter( content_type=ContentType.objects.get_for_model(type(self)), object_id=self.pk ).select_related('user', 'event') + + +class EventBoundModelMixin: + event_lookup = 'event' + + @classmethod + def for_event(cls, event): + return cls.all.filter(**{ + cls.event_lookup: event + }) + + @classmethod + def check(cls, **kwargs): + try: + errors = super(cls).check(**kwargs) + except AttributeError: + errors = [] + if hasattr(cls, 'objects'): + errors.append( + checks.Error( + 'Default model manager "objects" defined.', + hint='Replace the objects manager by a manager called "all".', + obj=cls, + id='pretixbase.E001', + ) + ) + if not hasattr(cls, 'all'): + errors.append( + checks.Error( + 'Model manager "all" not defined.', + obj=cls, + id='pretixbase.E002', + ) + ) + return errors diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 94e234ad7..d4b54bddc 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -234,14 +234,14 @@ class Event(LoggedModel): ), tz) def copy_data_from(self, other): - from . import ItemAddOn, ItemCategory, Item, Question, Quota + from . import ItemAddOn, Item, Question, Quota from ..signals import event_copy_data self.plugins = other.plugins self.save() category_map = {} - for c in ItemCategory.objects.filter(event=other): + for c in other.categories.all(): category_map[c.pk] = c c.pk = None c.event = self diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py index a72213669..47a1872ef 100644 --- a/src/pretix/base/models/items.py +++ b/src/pretix/base/models/items.py @@ -14,12 +14,12 @@ from django.utils.translation import ugettext_lazy as _ from i18nfield.fields import I18nCharField, I18nTextField from pretix.base.decimal import round_decimal -from pretix.base.models.base import LoggedModel +from pretix.base.models.base import EventBoundModelMixin, LoggedModel from .event import Event -class ItemCategory(LoggedModel): +class ItemCategory(EventBoundModelMixin, LoggedModel): """ Items can be sorted into these categories. @@ -53,6 +53,8 @@ class ItemCategory(LoggedModel): 'source for add-ons.') ) + all = models.Manager() + class Meta: verbose_name = _("Product category") verbose_name_plural = _("Product categories") diff --git a/src/pretix/plugins/sendmail/views.py b/src/pretix/plugins/sendmail/views.py index aa33e5e17..198cce98c 100644 --- a/src/pretix/plugins/sendmail/views.py +++ b/src/pretix/plugins/sendmail/views.py @@ -16,6 +16,7 @@ from pretix.base.models import InvoiceAddress, LogEntry, Order from pretix.base.services.mail import SendMailException, mail from pretix.control.permissions import EventPermissionRequiredMixin from pretix.multidomain.urlreverse import build_absolute_uri + from . import forms logger = logging.getLogger('pretix.plugins.sendmail') diff --git a/src/pretix/plugins/ticketoutputpdf/views.py b/src/pretix/plugins/ticketoutputpdf/views.py index 043193de7..c71ee1520 100644 --- a/src/pretix/plugins/ticketoutputpdf/views.py +++ b/src/pretix/plugins/ticketoutputpdf/views.py @@ -21,6 +21,7 @@ from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views import ChartContainingView from pretix.helpers.database import rolledback_transaction from pretix.plugins.ticketoutputpdf.signals import get_fonts + from .ticketoutput import PdfTicketOutput logger = logging.getLogger(__name__) diff --git a/src/tests/base/test_i18n.py b/src/tests/base/test_i18n.py index dbaa6fde5..079c1d5d8 100644 --- a/src/tests/base/test_i18n.py +++ b/src/tests/base/test_i18n.py @@ -92,6 +92,7 @@ class I18nFieldTest(TestCase): """ This test case tests the I18n*Field classes """ + @classmethod def setUpTestData(cls): o = Organizer.objects.create(name='Dummy', slug='dummy') @@ -101,8 +102,8 @@ class I18nFieldTest(TestCase): ) def test_save_load_cycle_plain_string(self): - obj = ItemCategory.objects.create(event=self.event, name="Hello") - obj = ItemCategory.objects.get(id=obj.id) + obj = ItemCategory.all.create(event=self.event, name="Hello") + obj = ItemCategory.all.get(id=obj.id) self.assertIsInstance(obj.name, LazyI18nString) translation.activate('en') self.assertEqual(str(obj.name), "Hello") @@ -110,14 +111,14 @@ class I18nFieldTest(TestCase): self.assertEqual(str(obj.name), "Hello") def test_save_load_cycle_i18n_string(self): - obj = ItemCategory.objects.create(event=self.event, - name=LazyI18nString( - { - 'de': 'Hallo', - 'en': 'Hello' - } - )) - obj = ItemCategory.objects.get(id=obj.id) + obj = ItemCategory.all.create(event=self.event, + name=LazyI18nString( + { + 'de': 'Hallo', + 'en': 'Hello' + } + )) + obj = ItemCategory.all.get(id=obj.id) self.assertIsInstance(obj.name, LazyI18nString) translation.activate('en') self.assertEqual(str(obj.name), "Hello") diff --git a/src/tests/base/test_models.py b/src/tests/base/test_models.py index d0cd1b238..9959fd858 100644 --- a/src/tests/base/test_models.py +++ b/src/tests/base/test_models.py @@ -687,8 +687,8 @@ class ItemCategoryTest(TestCase): ) def test_sorting(self): - c1 = ItemCategory.objects.create(event=self.event) - c2 = ItemCategory.objects.create(event=self.event) + c1 = ItemCategory.all.create(event=self.event) + c2 = ItemCategory.all.create(event=self.event) assert c1 < c2 c1.position = 2 c2.position = 1 diff --git a/src/tests/control/test_checkins.py b/src/tests/control/test_checkins.py index 41095b103..cb71ec22c 100644 --- a/src/tests/control/test_checkins.py +++ b/src/tests/control/test_checkins.py @@ -289,8 +289,8 @@ def checkin_list_with_addon_env(): team.limit_events.add(event) # item - cat_adm = ItemCategory.objects.create(event=event, name="Admission") - cat_workshop = ItemCategory.objects.create(event=event, name="Admission", is_addon=True) + cat_adm = ItemCategory.all.create(event=event, name="Admission") + cat_workshop = ItemCategory.all.create(event=event, name="Admission", is_addon=True) item_ticket = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True, category=cat_adm) item_workshop = Item.objects.create(event=event, name="Workshop", default_price=10, admission=False, category=cat_workshop) diff --git a/src/tests/control/test_items.py b/src/tests/control/test_items.py index 825bc9995..9d71ffaf9 100644 --- a/src/tests/control/test_items.py +++ b/src/tests/control/test_items.py @@ -37,7 +37,7 @@ class CategoriesTest(ItemFormTest): self.assertIn("Entry tickets", doc.select("#page-wrapper table")[0].text) def test_update(self): - c = ItemCategory.objects.create(event=self.event1, name="Entry tickets") + c = ItemCategory.all.create(event=self.event1, name="Entry tickets") doc = self.get_doc('/control/event/%s/%s/categories/%s/' % (self.orga1.slug, self.event1.slug, c.id)) form_data = extract_form_fields(doc.select('.container-fluid form')[0]) form_data['name_0'] = 'T-Shirts' @@ -46,11 +46,11 @@ class CategoriesTest(ItemFormTest): assert doc.select(".alert-success") self.assertIn("T-Shirts", doc.select("#page-wrapper table")[0].text) self.assertNotIn("Entry tickets", doc.select("#page-wrapper table")[0].text) - assert str(ItemCategory.objects.get(id=c.id).name) == 'T-Shirts' + assert str(ItemCategory.all.get(id=c.id).name) == 'T-Shirts' def test_sort(self): - c1 = ItemCategory.objects.create(event=self.event1, name="Entry tickets", position=0) - ItemCategory.objects.create(event=self.event1, name="T-Shirts", position=1) + c1 = ItemCategory.all.create(event=self.event1, name="Entry tickets", position=0) + ItemCategory.all.create(event=self.event1, name="T-Shirts", position=1) doc = self.get_doc('/control/event/%s/%s/categories/' % (self.orga1.slug, self.event1.slug)) self.assertIn("Entry tickets", doc.select("table > tbody > tr")[0].text) self.assertIn("T-Shirts", doc.select("table > tbody > tr")[1].text) @@ -66,14 +66,14 @@ class CategoriesTest(ItemFormTest): self.assertIn("T-Shirts", doc.select("table > tbody > tr")[1].text) def test_delete(self): - c = ItemCategory.objects.create(event=self.event1, name="Entry tickets") + c = ItemCategory.all.create(event=self.event1, name="Entry tickets") doc = self.get_doc('/control/event/%s/%s/categories/%s/delete' % (self.orga1.slug, self.event1.slug, c.id)) form_data = extract_form_fields(doc.select('.container-fluid form')[0]) doc = self.post_doc('/control/event/%s/%s/categories/%s/delete' % (self.orga1.slug, self.event1.slug, c.id), form_data) assert doc.select(".alert-success") self.assertNotIn("Entry tickets", doc.select("#page-wrapper")[0].text) - assert not ItemCategory.objects.filter(id=c.id).exists() + assert not ItemCategory.all.filter(id=c.id).exists() class QuestionsTest(ItemFormTest): @@ -264,7 +264,7 @@ class ItemsTest(ItemFormTest): require_voucher=True, allow_cancel=False) self.var1 = ItemVariation.objects.create(item=self.item2, value="Silver") self.var2 = ItemVariation.objects.create(item=self.item2, value="Gold") - self.addoncat = ItemCategory.objects.create(event=self.event1, name="Item category") + self.addoncat = ItemCategory.all.create(event=self.event1, name="Item category") def test_move(self): self.client.post('/control/event/%s/%s/items/%s/down' % (self.orga1.slug, self.event1.slug, self.item1.id),) diff --git a/src/tests/control/test_views.py b/src/tests/control/test_views.py index 3b23c4d6b..a63546101 100644 --- a/src/tests/control/test_views.py +++ b/src/tests/control/test_views.py @@ -26,7 +26,7 @@ def item(event): @pytest.fixture def item_category(event): - return ItemCategory.objects.create(event=event) + return ItemCategory.all.create(event=event) @pytest.fixture diff --git a/src/tests/plugins/paypal/test_checkout.py b/src/tests/plugins/paypal/test_checkout.py index 53c9923a4..d6b68b1ac 100644 --- a/src/tests/plugins/paypal/test_checkout.py +++ b/src/tests/plugins/paypal/test_checkout.py @@ -18,7 +18,7 @@ def env(client): plugins='pretix.plugins.paypal', live=True ) - category = ItemCategory.objects.create(event=event, name="Everything", position=0) + category = ItemCategory.all.create(event=event, name="Everything", position=0) quota_tickets = Quota.objects.create(event=event, name='Tickets', size=5) ticket = Item.objects.create(event=event, name='Early-bird ticket', category=category, default_price=23, admission=True) diff --git a/src/tests/plugins/stripe/test_checkout.py b/src/tests/plugins/stripe/test_checkout.py index 0bbc91713..2d5c71098 100644 --- a/src/tests/plugins/stripe/test_checkout.py +++ b/src/tests/plugins/stripe/test_checkout.py @@ -27,7 +27,7 @@ def env(client): plugins='pretix.plugins.stripe', live=True ) - category = ItemCategory.objects.create(event=event, name="Everything", position=0) + category = ItemCategory.all.create(event=event, name="Everything", position=0) quota_tickets = Quota.objects.create(event=event, name='Tickets', size=5) ticket = Item.objects.create(event=event, name='Early-bird ticket', category=category, default_price=23, admission=True) diff --git a/src/tests/plugins/test_sendmail.py b/src/tests/plugins/test_sendmail.py index 4524333ab..85e411d8b 100644 --- a/src/tests/plugins/test_sendmail.py +++ b/src/tests/plugins/test_sendmail.py @@ -30,7 +30,7 @@ def item(event): @pytest.fixture def item_category(event): """Returns an item category instance""" - return ItemCategory.objects.create(event=event) + return ItemCategory.all.create(event=event) @pytest.fixture diff --git a/src/tests/presale/test_cart.py b/src/tests/presale/test_cart.py index cf8bd5485..b687ac3c6 100644 --- a/src/tests/presale/test_cart.py +++ b/src/tests/presale/test_cart.py @@ -24,7 +24,7 @@ class CartTestMixin: date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc), live=True ) - self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0) + self.category = ItemCategory.all.create(event=self.event, name="Everything", position=0) self.quota_shirts = Quota.objects.create(event=self.event, name='Shirts', size=2) self.shirt = Item.objects.create(event=self.event, name='T-Shirt', category=self.category, default_price=12) self.quota_shirts.items.add(self.shirt) @@ -1013,7 +1013,7 @@ class CartTest(CartTestMixin, TestCase): class CartAddonTest(CartTestMixin, TestCase): def setUp(self): super().setUp() - self.workshopcat = ItemCategory.objects.create(name="Workshops", is_addon=True, event=self.event) + self.workshopcat = ItemCategory.all.create(name="Workshops", is_addon=True, event=self.event) self.workshopquota = Quota.objects.create(event=self.event, name='Workshop 1', size=5) self.workshop1 = Item.objects.create(event=self.event, name='Workshop 1', category=self.workshopcat, default_price=12) diff --git a/src/tests/presale/test_checkout.py b/src/tests/presale/test_checkout.py index b2850e4ae..93f83ccaa 100644 --- a/src/tests/presale/test_checkout.py +++ b/src/tests/presale/test_checkout.py @@ -24,7 +24,7 @@ class CheckoutTestCase(TestCase): plugins='pretix.plugins.stripe,pretix.plugins.banktransfer', live=True ) - self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0) + self.category = ItemCategory.all.create(event=self.event, name="Everything", position=0) self.quota_tickets = Quota.objects.create(event=self.event, name='Tickets', size=5) self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', category=self.category, default_price=23, admission=True) @@ -36,7 +36,7 @@ class CheckoutTestCase(TestCase): self.session_key = self.client.cookies.get(settings.SESSION_COOKIE_NAME).value self._set_session('email', 'admin@localhost') - self.workshopcat = ItemCategory.objects.create(name="Workshops", is_addon=True, event=self.event) + self.workshopcat = ItemCategory.all.create(name="Workshops", is_addon=True, event=self.event) self.workshopquota = Quota.objects.create(event=self.event, name='Workshop 1', size=5) self.workshop1 = Item.objects.create(event=self.event, name='Workshop 1', category=self.workshopcat, default_price=12) diff --git a/src/tests/presale/test_event.py b/src/tests/presale/test_event.py index 7b9964046..8b8b78cc8 100644 --- a/src/tests/presale/test_event.py +++ b/src/tests/presale/test_event.py @@ -116,7 +116,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest): self.assertNotIn("Early-bird", html) def test_simple_with_category(self): - c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0) + c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0) q = Quota.objects.create(event=self.event, name='Quota', size=2) item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0) q.items.add(item) @@ -125,13 +125,13 @@ class ItemDisplayTest(EventTestMixin, SoupTest): self.assertIn("Early-bird", doc.select("section:nth-of-type(1) div:nth-of-type(1)")[0].text) def test_simple_without_quota(self): - c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0) + c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0) Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0) resp = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)) self.assertNotIn("Early-bird", resp.rendered_content) def test_no_variations_in_quota(self): - c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0) + c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0) q = Quota.objects.create(event=self.event, name='Quota', size=2) item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0) ItemVariation.objects.create(item=item, value='Blue') @@ -140,7 +140,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest): self.assertNotIn("Early-bird", resp.rendered_content) def test_one_variation_in_quota(self): - c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0) + c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0) q = Quota.objects.create(event=self.event, name='Quota', size=2) item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0) var1 = ItemVariation.objects.create(item=item, value='Red') @@ -150,7 +150,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest): self._assert_variation_found() def test_one_variation_in_unlimited_quota(self): - c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0) + c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0) q = Quota.objects.create(event=self.event, name='Quota', size=None) item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=0) var1 = ItemVariation.objects.create(item=item, value='Red') @@ -166,7 +166,7 @@ class ItemDisplayTest(EventTestMixin, SoupTest): self.assertNotIn("Black", doc.select("section:nth-of-type(1)")[0].text) def test_variation_prices_in_quota(self): - c = ItemCategory.objects.create(event=self.event, name="Entry tickets", position=0) + c = ItemCategory.all.create(event=self.event, name="Entry tickets", position=0) q = Quota.objects.create(event=self.event, name='Quota', size=2) item = Item.objects.create(event=self.event, name='Early-bird ticket', category=c, default_price=12) var1 = ItemVariation.objects.create(item=item, value='Red', default_price=14, position=1) diff --git a/src/tests/presale/test_orders.py b/src/tests/presale/test_orders.py index 0843cbd46..c51917d5e 100644 --- a/src/tests/presale/test_orders.py +++ b/src/tests/presale/test_orders.py @@ -25,7 +25,7 @@ class OrdersTest(TestCase): self.event.settings.set('payment_banktransfer__enabled', True) self.event.settings.set('ticketoutput_testdummy__enabled', True) - self.category = ItemCategory.objects.create(event=self.event, name="Everything", position=0) + self.category = ItemCategory.all.create(event=self.event, name="Everything", position=0) self.quota_shirts = Quota.objects.create(event=self.event, name='Shirts', size=2) self.shirt = Item.objects.create(event=self.event, name='T-Shirt', category=self.category, default_price=12) self.quota_shirts.items.add(self.shirt)