From da7539465aef43f0258188eb3be6ccce8e00af3c Mon Sep 17 00:00:00 2001 From: Guillaume Pellerin Date: Mon, 26 Sep 2016 13:18:12 +0200 Subject: [PATCH] Add Product lists to pages, fix admin fields order against translations --- app/local_settings.py | 6 ++ app/organization/core/admin.py | 12 +++ app/organization/network/admin.py | 9 +- app/organization/pages/admin.py | 6 +- app/organization/shop/admin.py | 12 ++- .../migrations/0004_auto_20160926_1144.py | 42 +++++++++ .../migrations/0005_auto_20160926_1230.py | 91 +++++++++++++++++++ app/organization/shop/models.py | 22 ++--- app/organization/shop/translation.py | 14 +-- app/templates/pages/custompage.html | 22 +++-- app/templates/pages/page.html | 2 + .../includes/product_list_square_style.html | 46 ++++++++++ 12 files changed, 243 insertions(+), 41 deletions(-) create mode 100644 app/organization/shop/migrations/0004_auto_20160926_1144.py create mode 100644 app/organization/shop/migrations/0005_auto_20160926_1230.py create mode 100644 app/templates/shop/includes/product_list_square_style.html diff --git a/app/local_settings.py b/app/local_settings.py index 8b702ed6..ef1e6401 100644 --- a/app/local_settings.py +++ b/app/local_settings.py @@ -108,6 +108,12 @@ ADMIN_MENU_ORDER = ( 'organization-projects.ProjectTopic', 'organization-projects.ProjectProgramType', )), + (_('Shop'), ('shop.Product', + 'organization-shop.ProductList', + 'shop.Order', + 'shop.DiscountCode', + 'shop.Sale', + )), (_('Jobs'), ('organization-job.JobOffer',)), (_('Festival'), ('organization-festival.Artist',)), (_('Users'), ('auth.User', 'auth.Group',)), diff --git a/app/organization/core/admin.py b/app/organization/core/admin.py index 4438e24c..abdeaffa 100644 --- a/app/organization/core/admin.py +++ b/app/organization/core/admin.py @@ -12,6 +12,18 @@ class KeywordAdmin(BaseTranslationModelAdmin): model = Keyword +class BaseTranslationOrderedModelAdmin(BaseTranslationModelAdmin): + + def get_fieldsets(self, request, obj = None): + res = super(BaseTranslationOrderedModelAdmin, self).get_fieldsets(request, obj) + for field in reversed(self.first_fields): + for trans_field in res[0][1]['fields']: + if field in trans_field: + index = res[0][1]['fields'].index(trans_field) + res[0][1]['fields'].insert(0, res[0][1]['fields'].pop(index)) + return res + + admin.site.register(LinkType) admin.site.unregister(BlogPost) admin.site.unregister(ThreadedComment) diff --git a/app/organization/network/admin.py b/app/organization/network/admin.py index 63fe4991..b2527e85 100644 --- a/app/organization/network/admin.py +++ b/app/organization/network/admin.py @@ -103,20 +103,13 @@ class PersonBlockInline(StackedDynamicInlineAdmin): model = PersonBlock -class PersonAdmin(BaseTranslationModelAdmin): +class PersonAdmin(BaseTranslationOrderedModelAdmin): model = Person inlines = [PersonActivityInline, PersonAudioInline, PersonImageInline, PersonVideoInline, PersonBlockInline, PersonLinkInline ] first_fields = ['last_name', 'first_name', 'title', 'gender', 'user'] search_fields = ['last_name', 'first_name'] - def get_fieldsets(self, request, obj = None): - res = super(PersonAdmin, self).get_fieldsets(request, obj) - for field in reversed(self.first_fields): - index = res[0][1]['fields'].index(field) - res[0][1]['fields'].insert(0, res[0][1]['fields'].pop(index)) - return res - class PersonListBlockInlineAdmin(TabularDynamicInlineAdmin): diff --git a/app/organization/pages/admin.py b/app/organization/pages/admin.py index c73ef8c3..fde7064f 100644 --- a/app/organization/pages/admin.py +++ b/app/organization/pages/admin.py @@ -59,9 +59,9 @@ class PersonListBlockAutocompleteInlineAdmin(TabularDynamicInlineAdmin): form = PageCustomPersonListForm -class PageProductBlockInline(TabularDynamicInlineAdmin): +class PageProductListInline(TabularDynamicInlineAdmin): - model = PageProductBlock + model = PageProductList class CustomPageAdmin(PageAdmin): @@ -72,7 +72,7 @@ class CustomPageAdmin(PageAdmin): PageVideoInline, PageLinkInline, PersonListBlockAutocompleteInlineAdmin, - PageProductBlockInline + PageProductListInline ] diff --git a/app/organization/shop/admin.py b/app/organization/shop/admin.py index 27502fb0..cc66060d 100644 --- a/app/organization/shop/admin.py +++ b/app/organization/shop/admin.py @@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from mezzanine.core.admin import * +from organization.core.admin import * from organization.projects.models import * from organization.pages.models import * from organization.media.models import Video, Audio @@ -13,14 +14,15 @@ from organization.shop.models import * from cartridge.shop.admin import * -class ProductBlockProductInline(TabularDynamicInlineAdmin): +class ProductListProductInline(TabularDynamicInlineAdmin): - model = ProductBlockProduct + model = ProductListProduct -class ProductBlockAdmin(BaseTranslationModelAdmin): +class ProductListAdmin(BaseTranslationOrderedModelAdmin): - inlines = [ProductBlockProductInline, ] + inlines = [ProductListProductInline, ] + first_fields = ['title', 'description',] class ProductLinkInline(TabularDynamicInlineAdmin): @@ -33,6 +35,6 @@ class CustomProductAdmin(ProductAdmin): inlines = [ProductImageAdmin, ProductVariationAdmin, ProductLinkInline] -admin.site.register(ProductBlock, ProductBlockAdmin) +admin.site.register(ProductList, ProductListAdmin) admin.site.unregister(Product) admin.site.register(Product, CustomProductAdmin) diff --git a/app/organization/shop/migrations/0004_auto_20160926_1144.py b/app/organization/shop/migrations/0004_auto_20160926_1144.py new file mode 100644 index 00000000..7b7b78ed --- /dev/null +++ b/app/organization/shop/migrations/0004_auto_20160926_1144.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-26 09:44 +from __future__ import unicode_literals + +from django.db import migrations, models +import mezzanine.core.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('organization-shop', '0003_productlink'), + ] + + operations = [ + migrations.AddField( + model_name='productblock', + name='content', + field=mezzanine.core.fields.RichTextField(default='', verbose_name='Content'), + preserve_default=False, + ), + migrations.AddField( + model_name='productblock', + name='content_en', + field=mezzanine.core.fields.RichTextField(null=True, verbose_name='Content'), + ), + migrations.AddField( + model_name='productblock', + name='content_fr', + field=mezzanine.core.fields.RichTextField(null=True, verbose_name='Content'), + ), + migrations.AddField( + model_name='productblock', + name='description_en', + field=models.TextField(blank=True, null=True, verbose_name='description'), + ), + migrations.AddField( + model_name='productblock', + name='description_fr', + field=models.TextField(blank=True, null=True, verbose_name='description'), + ), + ] diff --git a/app/organization/shop/migrations/0005_auto_20160926_1230.py b/app/organization/shop/migrations/0005_auto_20160926_1230.py new file mode 100644 index 00000000..91c5872e --- /dev/null +++ b/app/organization/shop/migrations/0005_auto_20160926_1230.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-09-26 10:30 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import mezzanine.core.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0008_auto_20160907_1726'), + ('pages', '0005_auto_20160923_1219'), + ('organization-shop', '0004_auto_20160926_1144'), + ] + + operations = [ + migrations.CreateModel( + name='PageProductList', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'verbose_name': 'product list', + 'verbose_name_plural': 'product lists', + }, + ), + migrations.CreateModel( + name='ProductListProduct', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('_order', mezzanine.core.fields.OrderField(null=True, verbose_name='Order')), + ], + options={ + 'verbose_name': 'product', + 'verbose_name_plural': 'products', + 'ordering': ('_order',), + }, + ), + migrations.RenameModel( + old_name='ProductBlock', + new_name='ProductList', + ), + migrations.RemoveField( + model_name='pageproductblock', + name='page', + ), + migrations.RemoveField( + model_name='pageproductblock', + name='product_block', + ), + migrations.RemoveField( + model_name='productblockproduct', + name='product', + ), + migrations.RemoveField( + model_name='productblockproduct', + name='product_block', + ), + migrations.AlterModelOptions( + name='productlist', + options={'verbose_name': 'product list', 'verbose_name_plural': 'product lists'}, + ), + migrations.DeleteModel( + name='PageProductBlock', + ), + migrations.DeleteModel( + name='ProductBlockProduct', + ), + migrations.AddField( + model_name='productlistproduct', + name='list', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='products', to='organization-shop.ProductList', verbose_name='product list'), + ), + migrations.AddField( + model_name='productlistproduct', + name='product', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='lists', to='shop.Product', verbose_name='product'), + ), + migrations.AddField( + model_name='pageproductlist', + name='list', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pages', to='organization-shop.ProductList', verbose_name='product list'), + ), + migrations.AddField( + model_name='pageproductlist', + name='page', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='product_lists', to='pages.Page', verbose_name='page'), + ), + ] diff --git a/app/organization/shop/models.py b/app/organization/shop/models.py index cf1588a9..30db82e5 100644 --- a/app/organization/shop/models.py +++ b/app/organization/shop/models.py @@ -15,22 +15,22 @@ PRODUCT_LIST_STYLE_CHOICES = [ ] -class ProductBlock(Titled): +class ProductList(Titled, RichText): style = models.CharField(_('style'), max_length=16, choices=PRODUCT_LIST_STYLE_CHOICES) class Meta: - verbose_name = _("product block") - verbose_name_plural = _("product blocks") + verbose_name = _("product list") + verbose_name_plural = _("product lists") def __str__(self): return self.title -class ProductBlockProduct(Orderable): +class ProductListProduct(Orderable): - product_block = models.ForeignKey(ProductBlock, verbose_name=_('product block'), related_name='products', blank=True, null=True, on_delete=models.SET_NULL) - product = models.ForeignKey(Product, verbose_name=_('product'), related_name='blocks', blank=True, null=True, on_delete=models.SET_NULL) + list = models.ForeignKey(ProductList, verbose_name=_('product list'), related_name='products', blank=True, null=True, on_delete=models.SET_NULL) + product = models.ForeignKey(Product, verbose_name=_('product'), related_name='lists', blank=True, null=True, on_delete=models.SET_NULL) class Meta: verbose_name = _("product") @@ -38,14 +38,14 @@ class ProductBlockProduct(Orderable): -class PageProductBlock(models.Model): +class PageProductList(models.Model): - page = models.ForeignKey('pages.Page', verbose_name=_('page'), related_name='product_blocks', blank=True, null=True, on_delete=models.SET_NULL) - product_block = models.ForeignKey('organization-shop.ProductBlock', verbose_name=_('product block'), related_name='pages', blank=True, null=True, on_delete=models.SET_NULL) + page = models.ForeignKey('pages.Page', verbose_name=_('page'), related_name='product_lists', blank=True, null=True, on_delete=models.SET_NULL) + list = models.ForeignKey('organization-shop.ProductList', verbose_name=_('product list'), related_name='pages', blank=True, null=True, on_delete=models.SET_NULL) class Meta: - verbose_name = _("product block") - verbose_name_plural = _("product blocks") + verbose_name = _("product list") + verbose_name_plural = _("product lists") class ProductLink(Link): diff --git a/app/organization/shop/translation.py b/app/organization/shop/translation.py index 57d5a266..9f3c1acc 100644 --- a/app/organization/shop/translation.py +++ b/app/organization/shop/translation.py @@ -4,20 +4,20 @@ from organization.shop.models import * -@register(ProductBlock) -class ProductBlockTranslationOptions(TranslationOptions): +@register(ProductList) +class ProductListTranslationOptions(TranslationOptions): - fields = ['title',] + fields = ['title', 'description', 'content'] -@register(ProductBlockProduct) -class ProductBlockProductTranslationOptions(TranslationOptions): +@register(ProductListProduct) +class ProductListProductTranslationOptions(TranslationOptions): pass -@register(PageProductBlock) -class PageProductBlockTranslationOptions(TranslationOptions): +@register(PageProductList) +class PageProductListTranslationOptions(TranslationOptions): pass diff --git a/app/templates/pages/custompage.html b/app/templates/pages/custompage.html index a6eca743..e4cbab50 100644 --- a/app/templates/pages/custompage.html +++ b/app/templates/pages/custompage.html @@ -99,13 +99,11 @@ {% endblock %} {% block page_person_list %} - {% for page_custom_person_list_block_inline in page.custompage.page_custom_person_list_block_inlines.all %} - {% with page_custom_person_list_block_inline.person_list_block as person_list_block %} - {% with "network/inc/person/list_"|add:person_list_block.style|add:"_style.html" as template %} - {% include template %} - {% endwith %} - {% endwith %} - {% endfor %} + {% for inline in page.custompage.page_custom_person_list_block_inlines.all %} + {% with "network/inc/person/list_"|add:inline.person_list_block.style|add:"_style.html" as template %} + {% include template %} + {% endwith %} + {% endfor %} {% endblock %} {% block page_sub_content %} @@ -114,6 +112,16 @@ {% endwith %} {% endblock %} +{% block products %} + {% for page_product_list in page.custompage.product_lists.all %} + {% with page_product_list.list as list %} + {% with "shop/includes/product_list_"|add:list.style|add:"_style.html" as template %} + {% include template %} + {% endwith %} + {% endwith %} + {% endfor %} +{% endblock %} + {% block logo %} {% with page.custompage.images.all|get_type:'logo' as images %} {% if images %} diff --git a/app/templates/pages/page.html b/app/templates/pages/page.html index 6cea6239..b2690f51 100644 --- a/app/templates/pages/page.html +++ b/app/templates/pages/page.html @@ -70,6 +70,8 @@ {% endblock %} {% block page_person_list %} {% endblock %} + {% block products %} + {% endblock %} {% block page_sub_content %} {% endblock %} {% block page_related_content %} diff --git a/app/templates/shop/includes/product_list_square_style.html b/app/templates/shop/includes/product_list_square_style.html new file mode 100644 index 00000000..d0e75d6f --- /dev/null +++ b/app/templates/shop/includes/product_list_square_style.html @@ -0,0 +1,46 @@ +{% load organization_tags mezzanine_tags %} +{% if list %} +
+
+
+
+
+

{{ list.title }}

+ {% if list.description %} +

{{ list.description }}

+ {% endif %} +
+
+
+ +
+
+ {% for product_inline in list.products.all %} + {% with product_inline.product as product %} +
+
+ {% if product.images.all %} +
+ +
+ product +
+
+
+ {% endif %} +
+

{{ product.title }}

+ {% if product.description %} +
{{ product.description|richtext_filters|safe|truncatechars_html:255 }}
+ {% elif product.content %} +
{{ product.content|richtext_filters|safe|truncatechars_html:255 }}
+ {% endif %} +
+
+
+ {% endwith %} + {% endfor %} +
+
+
+{% endif %} -- 2.39.5