From 59eac8987a16a7fc35782b4ac276bf904f269d79 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Sun, 11 Jan 2015 17:47:43 +0100 Subject: [PATCH] Tests, fixes and creating items --- src/tixlbase/models.py | 20 ++++++++-- src/tixlbase/tests/test_middleware.py | 6 +++ src/tixlbase/tests/test_models.py | 40 ++++++++++++++++++- .../templates/tixlcontrol/item/base.html | 19 ++++++--- .../templates/tixlcontrol/items/index.html | 5 ++- src/tixlcontrol/urls.py | 1 + src/tixlcontrol/views/item.py | 29 ++++++++++++-- 7 files changed, 106 insertions(+), 14 deletions(-) diff --git a/src/tixlbase/models.py b/src/tixlbase/models.py index cd4621c7d3..8f3f00ad46 100644 --- a/src/tixlbase/models.py +++ b/src/tixlbase/models.py @@ -51,10 +51,24 @@ class Versionable(BaseVersionable): earlier_version.version_end_date = forced_version_date earlier_version.save() + for field in earlier_version._meta.many_to_many: + earlier_version.clone_relations_shallow(later_version, field.attname, forced_version_date) + + if hasattr(earlier_version._meta, 'many_to_many_related'): + for rel in earlier_version._meta.many_to_many_related: + earlier_version.clone_relations_shallow(later_version, rel.via_field_name, forced_version_date) + later_version.save() return later_version + def clone_relations_shallow(self, clone, manager_field_name, forced_version_date): + # Source: the original object, where relations are currently pointing to + source = getattr(self, manager_field_name) # returns a VersionedRelatedManager instance + # Destination: the clone, where the cloned relations should point to + source.through.objects.filter(**{source.source_field.attname: clone.id}).update(**{ + source.source_field.attname: self.id}) + class UserManager(BaseUserManager): """ @@ -156,11 +170,11 @@ class User(AbstractBaseUser, PermissionsMixin): return self.identifier def save(self, *args, **kwargs): - if self.identifier is None: + if not self.identifier: if self.event is None: self.identifier = self.email.lower() else: - self.identifier = "%s@%d.event.tixl" % (self.username.lower(), self.event.id) + self.identifier = "%s@%s.event.tixl" % (self.username.lower(), self.event.id) if not self.pk: self.identifier = self.identifier.lower() super().save(*args, **kwargs) @@ -179,7 +193,7 @@ class User(AbstractBaseUser, PermissionsMixin): elif not self.givenname and self.familyname: return self.familyname elif self.familyname and self.givenname: - return '%(family)s, %(given)s' % { + return _('%(family)s, %(given)s') % { 'family': self.familyname, 'given': self.givenname } diff --git a/src/tixlbase/tests/test_middleware.py b/src/tixlbase/tests/test_middleware.py index eadd26b511..a379328148 100644 --- a/src/tixlbase/tests/test_middleware.py +++ b/src/tixlbase/tests/test_middleware.py @@ -38,6 +38,12 @@ class LocaleDeterminationTest(TestCase): language = response['Content-Language'] self.assertEqual(language, self.TEST_LOCALE) + def test_unknown_browser_default(self): + c = Client(HTTP_ACCEPT_LANGUAGE='sjn') + response = c.get('/control/') + language = response['Content-Language'] + self.assertEqual(language, settings.LANGUAGE_CODE) + def test_cookie_settings(self): c = Client() cookies = c.cookies diff --git a/src/tixlbase/tests/test_models.py b/src/tixlbase/tests/test_models.py index 90d5ac4630..8d33e34cd5 100644 --- a/src/tixlbase/tests/test_models.py +++ b/src/tixlbase/tests/test_models.py @@ -3,7 +3,7 @@ from django.utils.timezone import now from tixlbase.models import ( Event, Organizer, Item, ItemVariation, - Property, PropertyValue + Property, PropertyValue, User ) from tixlbase.types import VariationDict @@ -139,3 +139,41 @@ class ItemVariationsTest(TestCase): ['L', 'blue'], ])) self.assertEqual(num_variations, 1) + + +class VersionableTestCase(TestCase): + + def test_shallow_cone(self): + o = Organizer.objects.create(name='Dummy', slug='dummy') + event = Event.objects.create( + organizer=o, name='Dummy', slug='dummy', + date_from=now(), + ) + old = Item.objects.create(event=event, name='Dummy', default_price=14) + prop = Property.objects.create(event=event, name='Size') + old.properties.add(prop) + new = old.clone_shallow() + self.assertIsNone(new.version_end_date) + self.assertIsNotNone(old.version_end_date) + self.assertEqual(new.properties.count(), 0) + self.assertEqual(old.properties.count(), 1) + + +class UserTestCase(TestCase): + + def test_identifier_local(self): + o = Organizer.objects.create(name='Dummy', slug='dummy') + event = Event.objects.create( + organizer=o, name='Dummy', slug='dummy', + date_from=now(), + ) + u = User(event=event, username='tester') + u.set_password("test") + u.save() + self.assertEqual(u.identifier, "%s@%s.event.tixl" % (u.username.lower(), event.id)) + + def test_identifier_global(self): + u = User(email='test@example.com') + u.set_password("test") + u.save() + self.assertEqual(u.identifier, "test@example.com") diff --git a/src/tixlcontrol/templates/tixlcontrol/item/base.html b/src/tixlcontrol/templates/tixlcontrol/item/base.html index 8f9dc3058e..ac20434a87 100644 --- a/src/tixlcontrol/templates/tixlcontrol/item/base.html +++ b/src/tixlcontrol/templates/tixlcontrol/item/base.html @@ -2,12 +2,19 @@ {% load i18n %} {% block title %}{{ item.name }} :: {% trans "Item" %}{% endblock %} {% block content %} -

{% trans "Modify item:" %} {{ item.name }}

- + {% if item.identity %} +

{% trans "Modify item:" %} {{ item.name }}

+ + {% else %} +

{% trans "Create item" %}

+

{% blocktrans trimmed %} + You will be able to adjust further settings in the next step. + {% endblocktrans %}

+ {% endif %} {% if item.identity and not item.quotas.exists %}
{% blocktrans trimmed %} diff --git a/src/tixlcontrol/templates/tixlcontrol/items/index.html b/src/tixlcontrol/templates/tixlcontrol/items/index.html index 4459df7dd4..297300784b 100644 --- a/src/tixlcontrol/templates/tixlcontrol/items/index.html +++ b/src/tixlcontrol/templates/tixlcontrol/items/index.html @@ -3,6 +3,9 @@ {% block title %}{% trans "Items" %}{% endblock %} {% block inside %}

{% trans "Items" %}

+

+ {% trans "Create new item" %} +

@@ -15,7 +18,7 @@ - + {% endfor %} diff --git a/src/tixlcontrol/urls.py b/src/tixlcontrol/urls.py index ef93951062..f7bb3be77c 100644 --- a/src/tixlcontrol/urls.py +++ b/src/tixlcontrol/urls.py @@ -21,6 +21,7 @@ urlpatterns += patterns( url(r'^settings/$', event.EventUpdate.as_view(), name='event.settings'), url(r'^settings/plugins$', event.EventPlugins.as_view(), name='event.settings.plugins'), url(r'^items/$', item.ItemList.as_view(), name='event.items'), + url(r'^items/add$', item.ItemCreate.as_view(), name='event.items.add'), url(r'^items/(?P[0-9a-f-]+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'), url(r'^items/(?P[0-9a-f-]+)/variations$', item.ItemVariations.as_view(), name='event.item.variations'), diff --git a/src/tixlcontrol/views/item.py b/src/tixlcontrol/views/item.py index b97ef99beb..611196cc8d 100644 --- a/src/tixlcontrol/views/item.py +++ b/src/tixlcontrol/views/item.py @@ -513,11 +513,12 @@ class QuotaEditorMixin: # optimization of tixlbase.models.Versionable.clone_shallow() # items = self.object.items.all() # variations = self.object.variations.all() + self.object = form.instance for item in self.items: field = form.fields['item_%s' % item.identity] data = form.cleaned_data['item_%s' % item.identity] if isinstance(field, VariationsField): - self.object.variations.add(data) + self.object.variations.add(*data) # for v in data: # if v not in variations: # self.object.variations.add(v) @@ -613,7 +614,7 @@ class ItemDetailMixin(SingleObjectMixin): return self.object -class ItemUpdateFormGeneral(VersionedModelForm): +class ItemFormGeneral(VersionedModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -637,8 +638,30 @@ class ItemUpdateFormGeneral(VersionedModelForm): ] +class ItemCreate(EventPermissionRequiredMixin, CreateView): + form_class = ItemFormGeneral + template_name = 'tixlcontrol/item/index.html' + permission = 'can_change_items' + + def get_success_url(self) -> str: + return reverse('control:event.item', kwargs={ + 'organizer': self.request.event.organizer.slug, + 'event': self.request.event.slug, + 'item': self.object.identity, + }) + '?success=true' + + def get_form_kwargs(self): + """ + Returns the keyword arguments for instantiating the form. + """ + newinst = Item(event=self.request.event) + kwargs = super().get_form_kwargs() + kwargs.update({'instance': newinst}) + return kwargs + + class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateView): - form_class = ItemUpdateFormGeneral + form_class = ItemFormGeneral template_name = 'tixlcontrol/item/index.html' permission = 'can_change_items'
{{ i.name }}{{ i.category }}{% if i.category %}{{ i.category }}{% endif %}