diff --git a/artel/artel/settings/__pycache__/base.cpython-311.pyc b/artel/artel/settings/__pycache__/base.cpython-311.pyc
index 8e092d9..140581b 100644
Binary files a/artel/artel/settings/__pycache__/base.cpython-311.pyc and b/artel/artel/settings/__pycache__/base.cpython-311.pyc differ
diff --git a/artel/artel/settings/base.py b/artel/artel/settings/base.py
index f8add95..8663caf 100644
--- a/artel/artel/settings/base.py
+++ b/artel/artel/settings/base.py
@@ -25,7 +25,8 @@ BASE_DIR = os.path.dirname(PROJECT_DIR)
INSTALLED_APPS = [
"home",
- "exhibitions",
+ "store",
+ "blog",
"search",
"wagtail.contrib.forms",
"wagtail.contrib.redirects",
@@ -37,7 +38,9 @@ INSTALLED_APPS = [
"wagtail.images",
"wagtail.search",
"wagtail.admin",
+ 'wagtail.contrib.modeladmin',
"wagtail",
+ "wagtailmenus",
"modelcluster",
"taggit",
"django.contrib.admin",
@@ -74,6 +77,7 @@ TEMPLATES = [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
+ 'wagtailmenus.context_processors.wagtailmenus',
],
},
},
diff --git a/artel/artel/templates/base.html b/artel/artel/templates/base.html
index 28f6d95..1b32201 100644
--- a/artel/artel/templates/base.html
+++ b/artel/artel/templates/base.html
@@ -1,4 +1,5 @@
{% load static wagtailcore_tags wagtailuserbar %}
+{% load menu_tags %}
@@ -33,8 +34,14 @@
{% wagtailuserbar %}
-
- {% block content %}{% endblock %}
+
+
+ {% main_menu template="menu/custom_main_menu.html" %}
+
+
+ {% block content %}{% endblock %}
+
+
{# Global javascript #}
diff --git a/artel/artel/templates/menu/custom_main_menu.html b/artel/artel/templates/menu/custom_main_menu.html
new file mode 100644
index 0000000..939c5c8
--- /dev/null
+++ b/artel/artel/templates/menu/custom_main_menu.html
@@ -0,0 +1,14 @@
+
+ {% for item in menu_items %}
+ -
+ {{ item.text }}
+ {% if item.sub_menu %}
+
+ {% endif %}
+
+ {% endfor %}
+
\ No newline at end of file
diff --git a/artel/exhibitions/__init__.py b/artel/blog/__init__.py
similarity index 100%
rename from artel/exhibitions/__init__.py
rename to artel/blog/__init__.py
diff --git a/artel/exhibitions/admin.py b/artel/blog/admin.py
similarity index 100%
rename from artel/exhibitions/admin.py
rename to artel/blog/admin.py
diff --git a/artel/exhibitions/apps.py b/artel/blog/apps.py
similarity index 60%
rename from artel/exhibitions/apps.py
rename to artel/blog/apps.py
index b8d3471..94788a5 100644
--- a/artel/exhibitions/apps.py
+++ b/artel/blog/apps.py
@@ -1,6 +1,6 @@
from django.apps import AppConfig
-class ExhibitionsConfig(AppConfig):
+class BlogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
- name = 'exhibitions'
+ name = 'blog'
diff --git a/artel/blog/migrations/0001_initial.py b/artel/blog/migrations/0001_initial.py
new file mode 100644
index 0000000..1b511ac
--- /dev/null
+++ b/artel/blog/migrations/0001_initial.py
@@ -0,0 +1,48 @@
+# Generated by Django 4.1.8 on 2023-04-28 20:41
+
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import modelcluster.fields
+import wagtail.fields
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('wagtailcore', '0083_workflowcontenttype'),
+ ('wagtailimages', '0025_alter_image_file_alter_rendition_file'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='BlogPage',
+ fields=[
+ ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')),
+ ('create_date', models.DateField(auto_now_add=True)),
+ ('edit_date', models.DateField(auto_now=True)),
+ ('body', wagtail.fields.RichTextField()),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=('wagtailcore.page',),
+ ),
+ migrations.CreateModel(
+ name='BlogPageGalleryImage',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('sort_order', models.IntegerField(blank=True, editable=False, null=True)),
+ ('caption', models.CharField(blank=True, max_length=250)),
+ ('order', models.IntegerField(validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1000)])),
+ ('image', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='wagtailimages.image')),
+ ('page', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='gallery_images', to='blog.blogpage')),
+ ],
+ options={
+ 'ordering': ['sort_order'],
+ 'abstract': False,
+ },
+ ),
+ ]
diff --git a/artel/exhibitions/migrations/__init__.py b/artel/blog/migrations/__init__.py
similarity index 100%
rename from artel/exhibitions/migrations/__init__.py
rename to artel/blog/migrations/__init__.py
diff --git a/artel/blog/models.py b/artel/blog/models.py
new file mode 100644
index 0000000..7ab6502
--- /dev/null
+++ b/artel/blog/models.py
@@ -0,0 +1,47 @@
+from django.db import models
+from django.core.validators import (
+ MinValueValidator,
+ MaxValueValidator
+)
+
+from wagtail.models import Page, Orderable
+from wagtail.fields import RichTextField
+from wagtail.admin.panels import (
+ FieldPanel,
+ InlinePanel
+)
+from wagtail.search import index
+from modelcluster.fields import ParentalKey
+
+
+class BlogPage(Page):
+ create_date = models.DateField(auto_now_add=True)
+ edit_date = models.DateField(auto_now=True)
+
+ body = RichTextField()
+
+ content_panels = Page.content_panels + [
+ FieldPanel("body"),
+ InlinePanel("gallery_images")
+ ]
+
+
+class BlogPageGalleryImage(Orderable):
+ page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
+ image = models.ForeignKey(
+ 'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
+ )
+ caption = models.CharField(blank=True, max_length=250)
+
+ order = models.IntegerField(
+ validators=[
+ MinValueValidator(0),
+ MaxValueValidator(1000)
+ ]
+ )
+
+ panels = [
+ FieldPanel('order'),
+ FieldPanel('image'),
+ FieldPanel('caption'),
+ ]
diff --git a/artel/blog/templates/blog/blog_page.html b/artel/blog/templates/blog/blog_page.html
new file mode 100644
index 0000000..89d786b
--- /dev/null
+++ b/artel/blog/templates/blog/blog_page.html
@@ -0,0 +1,18 @@
+{% extends "base.html" %}
+
+{% load wagtailcore_tags wagtailimages_tags %}
+
+{% block content %}
+ {{ page.title }}
+ {{ page.date }}
+
+ {{ page.body|richtext }}
+
+ {% for item in page.gallery_images.all %}
+
+ {% image item.image fill-320x240 %}
+
{{ item.caption }}
+
+ {% endfor %}
+
+{% endblock %}
diff --git a/artel/exhibitions/tests.py b/artel/blog/tests.py
similarity index 100%
rename from artel/exhibitions/tests.py
rename to artel/blog/tests.py
diff --git a/artel/exhibitions/views.py b/artel/blog/views.py
similarity index 100%
rename from artel/exhibitions/views.py
rename to artel/blog/views.py
diff --git a/artel/exhibitions/__pycache__/__init__.cpython-311.pyc b/artel/exhibitions/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 1082b21..0000000
Binary files a/artel/exhibitions/__pycache__/__init__.cpython-311.pyc and /dev/null differ
diff --git a/artel/exhibitions/__pycache__/admin.cpython-311.pyc b/artel/exhibitions/__pycache__/admin.cpython-311.pyc
deleted file mode 100644
index 889cc9c..0000000
Binary files a/artel/exhibitions/__pycache__/admin.cpython-311.pyc and /dev/null differ
diff --git a/artel/exhibitions/__pycache__/apps.cpython-311.pyc b/artel/exhibitions/__pycache__/apps.cpython-311.pyc
deleted file mode 100644
index e261fd6..0000000
Binary files a/artel/exhibitions/__pycache__/apps.cpython-311.pyc and /dev/null differ
diff --git a/artel/exhibitions/__pycache__/models.cpython-311.pyc b/artel/exhibitions/__pycache__/models.cpython-311.pyc
deleted file mode 100644
index 452096e..0000000
Binary files a/artel/exhibitions/__pycache__/models.cpython-311.pyc and /dev/null differ
diff --git a/artel/exhibitions/migrations/__pycache__/0001_initial.cpython-311.pyc b/artel/exhibitions/migrations/__pycache__/0001_initial.cpython-311.pyc
deleted file mode 100644
index 53449be..0000000
Binary files a/artel/exhibitions/migrations/__pycache__/0001_initial.cpython-311.pyc and /dev/null differ
diff --git a/artel/exhibitions/migrations/__pycache__/__init__.cpython-311.pyc b/artel/exhibitions/migrations/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 9ce2682..0000000
Binary files a/artel/exhibitions/migrations/__pycache__/__init__.cpython-311.pyc and /dev/null differ
diff --git a/artel/exhibitions/models.py b/artel/exhibitions/models.py
deleted file mode 100644
index 3bf1e43..0000000
--- a/artel/exhibitions/models.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from django.db import models
-from wagtail.models import (
- Page,
- Orderable
-)
-from wagtail import fields
-from wagtail.admin.panels import (
- FieldPanel,
- InlinePanel
-)
-from modelcluster.fields import ParentalKey
-
-
-class ExhibitionIndexPage(Page):
- intro = fields.RichTextField(blank=True)
-
- content_panels = Page.content_panels + [
- FieldPanel('intro')
- ]
-
-
-class ExhibitionPage(Page):
- exhibition_desc = fields.RichTextField(blank=True)
-
- content_panels = Page.content_panels + [
- FieldPanel('exhibition_desc'),
- InlinePanel('exhibits', label="Exhibits")
- ]
-
-
-class Exhibit(Orderable):
- page = ParentalKey(ExhibitionPage, on_delete=models.CASCADE, related_name='exhibits')
- image = models.ForeignKey(
- 'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
- )
- title = models.CharField(max_length=250)
- slug = models.SlugField()
- exhibit_description = models.TextField(blank=True, default="")
-
- panels = [
- FieldPanel('image'),
- FieldPanel('caption'),
- FieldPanel("exhibit_description")
- ]
diff --git a/artel/exhibitions/templates/exhibitions/exhibition_index_page.html b/artel/exhibitions/templates/exhibitions/exhibition_index_page.html
deleted file mode 100644
index d58f2ff..0000000
--- a/artel/exhibitions/templates/exhibitions/exhibition_index_page.html
+++ /dev/null
@@ -1,17 +0,0 @@
-{% extends "base.html" %}
-
-{% load wagtailcore_tags %}
-
-{% block body_class %}template-blogindexpage{% endblock %}
-
-{% block content %}
- {{ page.title }}
-
- {{ page.intro|richtext }}
-
- {% for exhibition in page.get_children %}
-
- {{ exhibition.specific.exhibition_desc }}
- {% endfor %}
-
-{% endblock %}
\ No newline at end of file
diff --git a/artel/exhibitions/templates/exhibitions/exhibition_page.html b/artel/exhibitions/templates/exhibitions/exhibition_page.html
deleted file mode 100644
index 318c5c4..0000000
--- a/artel/exhibitions/templates/exhibitions/exhibition_page.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base.html" %}
-
-{% load wagtailcore_tags wagtailimages_tags %}
-
-{% block body_class %}template-blogpage{% endblock %}
-
-{% block content %}
- {{ page.title }}
-
- {% for item in page.exhibits.all %}
-
- {% image item.image max-320x200 %}
-
{{ item.caption }}
-
- {% endfor %}
-
-
-
-
-{% endblock %}
\ No newline at end of file
diff --git a/artel/home/templates/home/home_page.html b/artel/home/templates/home/home_page.html
index 85c0021..c923639 100644
--- a/artel/home/templates/home/home_page.html
+++ b/artel/home/templates/home/home_page.html
@@ -5,5 +5,7 @@
{% block body_class %}template-homepage{% endblock %}
{% block content %}
- {{ page.body|richtext }}
+
+ {{ page.body|richtext }}
+
{% endblock %}
\ No newline at end of file
diff --git a/artel/requirements.txt b/artel/requirements.txt
index f0b8e40..adb50bf 100644
--- a/artel/requirements.txt
+++ b/artel/requirements.txt
@@ -1,2 +1,3 @@
Django>=4.1,<4.2
wagtail>=4.2,<4.3
+wagtailmenus>=3.15, <=3.1.7
diff --git a/artel/store/admin.py b/artel/store/admin.py
index 8c38f3f..ffe0108 100644
--- a/artel/store/admin.py
+++ b/artel/store/admin.py
@@ -1,3 +1,47 @@
-from django.contrib import admin
+from django.forms import fields
-# Register your models here.
+from wagtail.contrib.modeladmin.options import (
+ ModelAdmin,
+ ModelAdminGroup,
+ modeladmin_register
+)
+from wagtail.admin.forms.models import WagtailAdminModelForm
+
+from store import models
+
+
+class ProductConfigAdmin(ModelAdmin):
+ model = models.ProductConfig
+ list_display = ("author__name", "color", "price")
+ search_fields = ("author__name", "color", "price")
+
+
+class ProductTemplateAdmin(ModelAdmin):
+ model = models.ProductTemplate
+ list_display = ("title", )
+
+
+class ProductAdminForm(WagtailAdminModelForm):
+
+ template_title = fields.CharField()
+ template_code = fields.CharField()
+ template_description = fields.CharField()
+
+ class Meta:
+ fields = ("template_title", "template_code", "template_description")
+ model = models.Product
+
+
+class ProductAdmin(ModelAdmin):
+ model = models.Product
+ form = ProductAdminForm
+
+
+class StoreAdminGroup(ModelAdminGroup):
+ menu_label = "Store"
+ menu_icon = 'folder-open-inverse'
+ menu_order = 200
+ items = (ProductConfigAdmin, ProductTemplateAdmin, ProductAdmin)
+
+
+modeladmin_register(StoreAdminGroup)
diff --git a/artel/store/migrations/0001_initial.py b/artel/store/migrations/0001_initial.py
new file mode 100644
index 0000000..046c795
--- /dev/null
+++ b/artel/store/migrations/0001_initial.py
@@ -0,0 +1,57 @@
+# Generated by Django 4.1.8 on 2023-04-25 22:22
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='ProductAuthor',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProductTemplate',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('title', models.CharField(max_length=255)),
+ ('code', models.CharField(max_length=255)),
+ ('description', models.TextField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProductImage',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('image', models.ImageField(upload_to='')),
+ ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='store.producttemplate')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProductConfig',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('color', models.CharField(max_length=255)),
+ ('size', models.CharField(max_length=50)),
+ ('price', models.FloatField()),
+ ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productauthor')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Product',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('config', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.productconfig')),
+ ('template', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='store.producttemplate')),
+ ],
+ ),
+ ]
diff --git a/artel/store/models.py b/artel/store/models.py
index cf5be90..8851557 100644
--- a/artel/store/models.py
+++ b/artel/store/models.py
@@ -1,16 +1,34 @@
from django.db import models
-class Product(models.Model):
- template = models.ForeignKey("exhibitions.Exhibit", on_delete=models.CASCADE)
-
-
-class ProductSource(models.Model):
+class ProductAuthor(models.Model):
name = models.CharField(max_length=255)
+ # TODO - author contact info? maybe foreignkey with user
+
+class ProductTemplate(models.Model):
+ title = models.CharField(max_length=255)
+ code = models.CharField(max_length=255)
+ description = models.TextField()
+
+ def get_images(self):
+ return self.images.objects.all().values_list("image")
+
+
+class ProductImage(models.Model):
+ template = models.ForeignKey(
+ ProductTemplate, on_delete=models.CASCADE, related_name="images"
+ )
+ image = models.ImageField()
class ProductConfig(models.Model):
- source = models.ForeignKey(ProductSource, on_delete=models.CASCADE)
+ author = models.ForeignKey(ProductAuthor, on_delete=models.CASCADE)
color = models.CharField(max_length=255)
-
+ size = models.CharField(max_length=50)
price = models.FloatField()
+
+
+class Product(models.Model):
+ template = models.ForeignKey(ProductTemplate, on_delete=models.CASCADE)
+ config = models.ForeignKey(ProductConfig, on_delete=models.CASCADE)
+