picata 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- LICENSE.md +24 -0
- README.md +59 -0
- components/HelloWorld.tsx +11 -0
- entrypoint.tsx +268 -0
- manage.py +15 -0
- picata/__init__.py +1 -0
- picata/apps.py +33 -0
- picata/blocks.py +175 -0
- picata/helpers/__init__.py +70 -0
- picata/helpers/wagtail.py +61 -0
- picata/log_utils.py +47 -0
- picata/middleware.py +54 -0
- picata/migrations/0001_initial.py +264 -0
- picata/migrations/0002_alter_article_content_alter_basicpage_content.py +112 -0
- picata/migrations/0003_alter_article_content_alter_basicpage_content.py +104 -0
- picata/migrations/0004_alter_article_content_alter_basicpage_content.py +105 -0
- picata/migrations/0005_socialsettings.py +48 -0
- picata/migrations/0006_alter_article_content.py +71 -0
- picata/migrations/0007_splitviewpage.py +69 -0
- picata/migrations/0008_alter_splitviewpage_content.py +96 -0
- picata/migrations/0009_alter_splitviewpage_content.py +111 -0
- picata/migrations/0010_alter_splitviewpage_content.py +105 -0
- picata/migrations/0011_alter_splitviewpage_options_and_more.py +113 -0
- picata/migrations/0012_alter_splitviewpage_content.py +109 -0
- picata/migrations/0013_alter_article_content.py +43 -0
- picata/migrations/0014_alter_article_content_alter_article_summary.py +24 -0
- picata/migrations/0015_alter_article_options_article_tagline_and_more.py +28 -0
- picata/migrations/0016_alter_article_options_alter_articletag_options_and_more.py +33 -0
- picata/migrations/0017_articletagrelation_alter_article_tags_and_more.py +35 -0
- picata/migrations/0018_rename_articletag_pagetag_and_more.py +21 -0
- picata/migrations/0019_rename_name_plural_articletype__name_plural.py +18 -0
- picata/migrations/0020_rename__name_plural_articletype__pluralised_name.py +18 -0
- picata/migrations/0021_rename_article_type_article_page_type.py +18 -0
- picata/migrations/0022_homepage.py +28 -0
- picata/migrations/__init__.py +0 -0
- picata/models.py +486 -0
- picata/settings/__init__.py +1 -0
- picata/settings/base.py +345 -0
- picata/settings/dev.py +94 -0
- picata/settings/mypy.py +7 -0
- picata/settings/prod.py +12 -0
- picata/settings/test.py +6 -0
- picata/static/picata/ada-profile.jpg +0 -0
- picata/static/picata/ada-social-bear.jpg +0 -0
- picata/static/picata/favicon.ico +0 -0
- picata/static/picata/fonts/Bitter-Light.ttf +0 -0
- picata/static/picata/fonts/Bitter-LightItalic.ttf +0 -0
- picata/static/picata/fonts/FiraCode-Light.ttf +0 -0
- picata/static/picata/fonts/FiraCode-SemiBold.ttf +0 -0
- picata/static/picata/fonts/Sacramento-Regular.ttf +0 -0
- picata/static/picata/fonts/ZillaSlab-Bold.ttf +0 -0
- picata/static/picata/fonts/ZillaSlab-BoldItalic.ttf +0 -0
- picata/static/picata/fonts/ZillaSlab-Light.ttf +0 -0
- picata/static/picata/fonts/ZillaSlab-LightItalic.ttf +0 -0
- picata/static/picata/fonts/ZillaSlabHighlight-Bold.ttf +0 -0
- picata/static/picata/icons.svg +56 -0
- picata/templates/picata/3_column.html +28 -0
- picata/templates/picata/404.html +11 -0
- picata/templates/picata/500.html +13 -0
- picata/templates/picata/_post_list.html +24 -0
- picata/templates/picata/article.html +20 -0
- picata/templates/picata/base.html +135 -0
- picata/templates/picata/basic_page.html +10 -0
- picata/templates/picata/blocks/icon_link_item.html +7 -0
- picata/templates/picata/blocks/icon_link_list.html +4 -0
- picata/templates/picata/blocks/icon_link_list_stream.html +3 -0
- picata/templates/picata/dl_view.html +18 -0
- picata/templates/picata/home_page.html +21 -0
- picata/templates/picata/post_listing.html +17 -0
- picata/templates/picata/previews/3col.html +73 -0
- picata/templates/picata/previews/dl.html +10 -0
- picata/templates/picata/previews/split.html +10 -0
- picata/templates/picata/previews/theme_gallery.html +158 -0
- picata/templates/picata/search_results.html +28 -0
- picata/templates/picata/split_view.html +15 -0
- picata/templates/picata/tags/site_menu.html +8 -0
- picata/templatetags/__init__.py +1 -0
- picata/templatetags/absolute_static.py +15 -0
- picata/templatetags/menu_tags.py +42 -0
- picata/templatetags/stringify.py +23 -0
- picata/transformers.py +60 -0
- picata/typing/__init__.py +19 -0
- picata/typing/wagtail.py +31 -0
- picata/urls.py +48 -0
- picata/validators.py +36 -0
- picata/views.py +80 -0
- picata/wagtail_hooks.py +43 -0
- picata/wsgi.py +15 -0
- picata-0.0.1.dist-info/METADATA +87 -0
- picata-0.0.1.dist-info/RECORD +94 -0
- picata-0.0.1.dist-info/WHEEL +4 -0
- picata-0.0.1.dist-info/licenses/LICENSE.md +24 -0
- pygments.sass +382 -0
- styles.sass +300 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
"""Generic helper-functions."""
|
2
|
+
# NB: Django's meta-class shenanigans over-complicate type hinting when QuerySets get involved.
|
3
|
+
# pyright: reportAttributeAccessIssue=false
|
4
|
+
|
5
|
+
from typing import cast
|
6
|
+
|
7
|
+
from django.http import HttpRequest
|
8
|
+
from wagtail.models import Page
|
9
|
+
from wagtail.query import PageQuerySet
|
10
|
+
|
11
|
+
from hpk.models import TaggedPage
|
12
|
+
|
13
|
+
from . import get_models_of_type
|
14
|
+
|
15
|
+
TAGGED_PAGE_TYPES = get_models_of_type(TaggedPage)
|
16
|
+
|
17
|
+
|
18
|
+
def visible_pages_qs(request: HttpRequest) -> PageQuerySet:
|
19
|
+
"""Return a QuerySet of all pages derived from `Page` visible to the user."""
|
20
|
+
pages = cast(PageQuerySet, Page.objects.all())
|
21
|
+
if not request.user.is_authenticated:
|
22
|
+
pages = pages.live()
|
23
|
+
return pages
|
24
|
+
|
25
|
+
|
26
|
+
def filter_pages_by_tags(pages: list[Page], tags: set[str]) -> list[TaggedPage]:
|
27
|
+
"""Filter a list of pages to those containing all of a list of tags."""
|
28
|
+
filtered_pages = []
|
29
|
+
for page in pages:
|
30
|
+
try:
|
31
|
+
if isinstance(page, tuple(TAGGED_PAGE_TYPES)):
|
32
|
+
page_tags = {tag.name for tag in page.tags.all()}
|
33
|
+
if set(tags).issubset(page_tags):
|
34
|
+
filtered_pages.append(page)
|
35
|
+
except AttributeError:
|
36
|
+
continue
|
37
|
+
return filtered_pages
|
38
|
+
|
39
|
+
|
40
|
+
def filter_pages_by_type(pages: list[Page], page_type_slugs: set[str]) -> list[Page]:
|
41
|
+
"""Filter a list of pages to those with a `page_type` matching any of the given slugs."""
|
42
|
+
filtered_pages = []
|
43
|
+
for page in pages:
|
44
|
+
try:
|
45
|
+
if (
|
46
|
+
hasattr(page, "page_type")
|
47
|
+
and page.page_type
|
48
|
+
and page.page_type.slug in page_type_slugs
|
49
|
+
):
|
50
|
+
filtered_pages.append(page)
|
51
|
+
except AttributeError:
|
52
|
+
continue
|
53
|
+
return filtered_pages
|
54
|
+
|
55
|
+
|
56
|
+
def page_preview_data(request: HttpRequest, page: Page) -> dict[str, str]:
|
57
|
+
"""Return a dictionary of available publication and preview data for a page."""
|
58
|
+
page_data = getattr(page, "preview_data", {}).copy()
|
59
|
+
if hasattr(page, "get_publication_data"):
|
60
|
+
page_data.update(page.get_publication_data(request))
|
61
|
+
return page_data
|
picata/log_utils.py
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
"""Customisations to the global logging system and custom logging classses."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
from logging.handlers import TimedRotatingFileHandler
|
5
|
+
|
6
|
+
# Define custom levels
|
7
|
+
TRACE_LEVEL = 5
|
8
|
+
SUCCESS_LEVEL = 25
|
9
|
+
|
10
|
+
logging.addLevelName(TRACE_LEVEL, "TRACE")
|
11
|
+
logging.addLevelName(SUCCESS_LEVEL, "SUCCESS")
|
12
|
+
|
13
|
+
|
14
|
+
# Handlers
|
15
|
+
|
16
|
+
|
17
|
+
class RotatingDailyFileHandler(TimedRotatingFileHandler):
|
18
|
+
"""Rotates file logs daily at midnight, with a week of backups by default."""
|
19
|
+
|
20
|
+
def __init__(self, filename: str, backup_days: int = 7) -> None:
|
21
|
+
"""Pass our defaults and given args to TimedRotatingFileHandler's __init__ method."""
|
22
|
+
super().__init__(filename, when="midnight", interval=1, backupCount=backup_days)
|
23
|
+
|
24
|
+
|
25
|
+
# Formatters
|
26
|
+
|
27
|
+
|
28
|
+
class FormatterWithEverything(logging.Formatter):
|
29
|
+
"""The *most* verbose logging formatter."""
|
30
|
+
|
31
|
+
def format(self, record: logging.LogRecord) -> str:
|
32
|
+
"""Return a ludicrously verbose log message format."""
|
33
|
+
verbose_message = (
|
34
|
+
f"LEVEL: {record.levelname}\n"
|
35
|
+
f"TIME: {self.formatTime(record)}\n"
|
36
|
+
f"LOGGER: {record.name}\n"
|
37
|
+
f"MODULE: {record.module}\n"
|
38
|
+
f"FUNC: {record.funcName}\n"
|
39
|
+
f"LINE: {record.lineno}\n"
|
40
|
+
f"PATH: {record.pathname}\n"
|
41
|
+
f"THREAD: {record.threadName}\n"
|
42
|
+
f"PROCESS: {record.process}\n"
|
43
|
+
f"MESSAGE: {record.getMessage()}\n"
|
44
|
+
)
|
45
|
+
if record.exc_info:
|
46
|
+
verbose_message += f"EXCEPTION: {self.formatException(record.exc_info)}\n"
|
47
|
+
return verbose_message
|
picata/middleware.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
"""HTML-processing middlware; should be placed last in (at the heart of) MIDDLEWARE."""
|
2
|
+
|
3
|
+
import logging
|
4
|
+
import re
|
5
|
+
from collections.abc import Callable
|
6
|
+
from typing import ClassVar
|
7
|
+
|
8
|
+
from django.http import HttpRequest, HttpResponse
|
9
|
+
from lxml import etree
|
10
|
+
|
11
|
+
from hpk.helpers import make_response
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
class HTMLProcessingMiddleware:
|
17
|
+
"""Middleware register for text/html document transformers."""
|
18
|
+
|
19
|
+
transformers: ClassVar[list[Callable[[etree._Element], None]]] = []
|
20
|
+
|
21
|
+
def __init__(self, get_response: Callable) -> None:
|
22
|
+
"""Standard middleware initialisation; get the get_response method."""
|
23
|
+
self.get_response = get_response
|
24
|
+
|
25
|
+
def __call__(self, request: HttpRequest) -> HttpResponse:
|
26
|
+
"""Filter the response through every registered transformer function."""
|
27
|
+
response = self.get_response(request)
|
28
|
+
|
29
|
+
if "text/html" in response.get("Content-Type", ""):
|
30
|
+
doctype = self.extract_doctype(response.content.decode())
|
31
|
+
tree = etree.fromstring(response.content, etree.HTMLParser()) # noqa: S320
|
32
|
+
if tree is not None:
|
33
|
+
for transformer in self.transformers:
|
34
|
+
transformer(tree)
|
35
|
+
processed_html = etree.tostring(
|
36
|
+
tree,
|
37
|
+
pretty_print=True, # type: ignore [reportCallIssue]
|
38
|
+
method="html", # type: ignore [reportCallIssue]
|
39
|
+
encoding=str, # type: ignore [reportCallIssue]
|
40
|
+
)
|
41
|
+
return make_response(response, f"{doctype}\n{processed_html}")
|
42
|
+
|
43
|
+
return response
|
44
|
+
|
45
|
+
@staticmethod
|
46
|
+
def extract_doctype(html: str) -> str:
|
47
|
+
"""Extract the DOCTYPE declaration from the HTML."""
|
48
|
+
match = re.match(r"^(<!DOCTYPE [^>]+>)", html, re.IGNORECASE)
|
49
|
+
return match.group(1) if match else ""
|
50
|
+
|
51
|
+
@classmethod
|
52
|
+
def add_transformer(cls, func: Callable[[etree._Element], None]) -> None:
|
53
|
+
"""Add a transformation function to the global pipeline."""
|
54
|
+
cls.transformers.append(func)
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# Generated by Django 5.1.4 on 2024-12-19 01:11
|
2
|
+
|
3
|
+
import django.db.models.deletion
|
4
|
+
import modelcluster.contrib.taggit
|
5
|
+
import modelcluster.fields
|
6
|
+
import wagtail.fields
|
7
|
+
from django.db import migrations, models
|
8
|
+
|
9
|
+
|
10
|
+
class Migration(migrations.Migration):
|
11
|
+
initial = True
|
12
|
+
|
13
|
+
dependencies = [
|
14
|
+
("taggit", "0006_rename_taggeditem_content_type_object_id_taggit_tagg_content_8fc721_idx"),
|
15
|
+
("wagtailcore", "0094_alter_page_locale"),
|
16
|
+
]
|
17
|
+
|
18
|
+
operations = [
|
19
|
+
migrations.CreateModel(
|
20
|
+
name="Article",
|
21
|
+
fields=[
|
22
|
+
(
|
23
|
+
"page_ptr",
|
24
|
+
models.OneToOneField(
|
25
|
+
auto_created=True,
|
26
|
+
on_delete=django.db.models.deletion.CASCADE,
|
27
|
+
parent_link=True,
|
28
|
+
primary_key=True,
|
29
|
+
serialize=False,
|
30
|
+
to="wagtailcore.page",
|
31
|
+
),
|
32
|
+
),
|
33
|
+
(
|
34
|
+
"summary",
|
35
|
+
wagtail.fields.RichTextField(
|
36
|
+
blank=True, help_text="A short summary, or tagline for the article."
|
37
|
+
),
|
38
|
+
),
|
39
|
+
(
|
40
|
+
"content",
|
41
|
+
wagtail.fields.StreamField(
|
42
|
+
[("section", 5), ("image", 3)],
|
43
|
+
blank=True,
|
44
|
+
block_lookup={
|
45
|
+
0: (
|
46
|
+
"wagtail.blocks.CharBlock",
|
47
|
+
(),
|
48
|
+
{"help_text": "Heading for this section.", "required": True},
|
49
|
+
),
|
50
|
+
1: (
|
51
|
+
"wagtail.blocks.IntegerBlock",
|
52
|
+
(),
|
53
|
+
{
|
54
|
+
"help_text": "Heading level",
|
55
|
+
"max_value": 6,
|
56
|
+
"min_value": 1,
|
57
|
+
"required": True,
|
58
|
+
},
|
59
|
+
),
|
60
|
+
2: (
|
61
|
+
"wagtail.blocks.RichTextBlock",
|
62
|
+
(),
|
63
|
+
{
|
64
|
+
"features": [
|
65
|
+
"bold",
|
66
|
+
"italic",
|
67
|
+
"link",
|
68
|
+
"ul",
|
69
|
+
"ol",
|
70
|
+
"document-link",
|
71
|
+
]
|
72
|
+
},
|
73
|
+
),
|
74
|
+
3: ("wagtail.images.blocks.ImageChooserBlock", (), {}),
|
75
|
+
4: (
|
76
|
+
"wagtail.blocks.StreamBlock",
|
77
|
+
[[("rich_text", 2), ("image", 3)]],
|
78
|
+
{
|
79
|
+
"help_text": "Content blocks for this section.",
|
80
|
+
"required": False,
|
81
|
+
},
|
82
|
+
),
|
83
|
+
5: (
|
84
|
+
"wagtail.blocks.StructBlock",
|
85
|
+
[[("heading", 0), ("level", 1), ("content", 4)]],
|
86
|
+
{},
|
87
|
+
),
|
88
|
+
},
|
89
|
+
help_text="Main content for the article.",
|
90
|
+
),
|
91
|
+
),
|
92
|
+
],
|
93
|
+
options={
|
94
|
+
"verbose_name": "Article",
|
95
|
+
"verbose_name_plural": "Articles",
|
96
|
+
},
|
97
|
+
bases=("wagtailcore.page",),
|
98
|
+
),
|
99
|
+
migrations.CreateModel(
|
100
|
+
name="ArticleTag",
|
101
|
+
fields=[
|
102
|
+
(
|
103
|
+
"id",
|
104
|
+
models.BigAutoField(
|
105
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
106
|
+
),
|
107
|
+
),
|
108
|
+
("name", models.CharField(max_length=100, unique=True, verbose_name="name")),
|
109
|
+
(
|
110
|
+
"slug",
|
111
|
+
models.SlugField(
|
112
|
+
allow_unicode=True, max_length=100, unique=True, verbose_name="slug"
|
113
|
+
),
|
114
|
+
),
|
115
|
+
],
|
116
|
+
options={
|
117
|
+
"verbose_name": "Article Tag",
|
118
|
+
"verbose_name_plural": "Article Tags",
|
119
|
+
},
|
120
|
+
),
|
121
|
+
migrations.CreateModel(
|
122
|
+
name="ArticleType",
|
123
|
+
fields=[
|
124
|
+
(
|
125
|
+
"id",
|
126
|
+
models.BigAutoField(
|
127
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
128
|
+
),
|
129
|
+
),
|
130
|
+
(
|
131
|
+
"name",
|
132
|
+
models.CharField(
|
133
|
+
help_text="Name of the article type.", max_length=100, unique=True
|
134
|
+
),
|
135
|
+
),
|
136
|
+
(
|
137
|
+
"name_plural",
|
138
|
+
models.CharField(
|
139
|
+
blank=True,
|
140
|
+
help_text="Plural form of the article type name (optional). Defaults to appending 's'.", # noqa: E501
|
141
|
+
max_length=100,
|
142
|
+
),
|
143
|
+
),
|
144
|
+
("slug", models.SlugField(max_length=100, unique=True)),
|
145
|
+
(
|
146
|
+
"description",
|
147
|
+
models.TextField(blank=True, help_text="Optional description of this type."),
|
148
|
+
),
|
149
|
+
],
|
150
|
+
),
|
151
|
+
migrations.CreateModel(
|
152
|
+
name="BasicPage",
|
153
|
+
fields=[
|
154
|
+
(
|
155
|
+
"page_ptr",
|
156
|
+
models.OneToOneField(
|
157
|
+
auto_created=True,
|
158
|
+
on_delete=django.db.models.deletion.CASCADE,
|
159
|
+
parent_link=True,
|
160
|
+
primary_key=True,
|
161
|
+
serialize=False,
|
162
|
+
to="wagtailcore.page",
|
163
|
+
),
|
164
|
+
),
|
165
|
+
(
|
166
|
+
"content",
|
167
|
+
wagtail.fields.StreamField(
|
168
|
+
[("rich_text", 0), ("image", 1)],
|
169
|
+
blank=True,
|
170
|
+
block_lookup={
|
171
|
+
0: ("wagtail.blocks.RichTextBlock", (), {}),
|
172
|
+
1: ("wagtail.images.blocks.ImageChooserBlock", (), {}),
|
173
|
+
},
|
174
|
+
help_text="Main content for the page.",
|
175
|
+
),
|
176
|
+
),
|
177
|
+
],
|
178
|
+
options={
|
179
|
+
"verbose_name": "Basic Page",
|
180
|
+
"verbose_name_plural": "Basic Pages",
|
181
|
+
},
|
182
|
+
bases=("wagtailcore.page",),
|
183
|
+
),
|
184
|
+
migrations.CreateModel(
|
185
|
+
name="PostGroupPage",
|
186
|
+
fields=[
|
187
|
+
(
|
188
|
+
"page_ptr",
|
189
|
+
models.OneToOneField(
|
190
|
+
auto_created=True,
|
191
|
+
on_delete=django.db.models.deletion.CASCADE,
|
192
|
+
parent_link=True,
|
193
|
+
primary_key=True,
|
194
|
+
serialize=False,
|
195
|
+
to="wagtailcore.page",
|
196
|
+
),
|
197
|
+
),
|
198
|
+
(
|
199
|
+
"intro",
|
200
|
+
wagtail.fields.RichTextField(
|
201
|
+
blank=True, help_text="An optional introduction to this group."
|
202
|
+
),
|
203
|
+
),
|
204
|
+
],
|
205
|
+
options={
|
206
|
+
"verbose_name": "Post Group",
|
207
|
+
"verbose_name_plural": "Post Groups",
|
208
|
+
},
|
209
|
+
bases=("wagtailcore.page",),
|
210
|
+
),
|
211
|
+
migrations.CreateModel(
|
212
|
+
name="ArticleTagItem",
|
213
|
+
fields=[
|
214
|
+
(
|
215
|
+
"id",
|
216
|
+
models.BigAutoField(
|
217
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
218
|
+
),
|
219
|
+
),
|
220
|
+
(
|
221
|
+
"content_object",
|
222
|
+
modelcluster.fields.ParentalKey(
|
223
|
+
on_delete=django.db.models.deletion.CASCADE,
|
224
|
+
related_name="tagged_items",
|
225
|
+
to="hpk.article",
|
226
|
+
),
|
227
|
+
),
|
228
|
+
(
|
229
|
+
"tag",
|
230
|
+
models.ForeignKey(
|
231
|
+
on_delete=django.db.models.deletion.CASCADE,
|
232
|
+
related_name="%(app_label)s_%(class)s_items",
|
233
|
+
to="taggit.tag",
|
234
|
+
),
|
235
|
+
),
|
236
|
+
],
|
237
|
+
options={
|
238
|
+
"abstract": False,
|
239
|
+
},
|
240
|
+
),
|
241
|
+
migrations.AddField(
|
242
|
+
model_name="article",
|
243
|
+
name="tags",
|
244
|
+
field=modelcluster.contrib.taggit.ClusterTaggableManager(
|
245
|
+
blank=True,
|
246
|
+
help_text="Tags for the article.",
|
247
|
+
through="hpk.ArticleTagItem",
|
248
|
+
to="taggit.Tag",
|
249
|
+
verbose_name="Tags",
|
250
|
+
),
|
251
|
+
),
|
252
|
+
migrations.AddField(
|
253
|
+
model_name="article",
|
254
|
+
name="article_type",
|
255
|
+
field=models.ForeignKey(
|
256
|
+
blank=True,
|
257
|
+
help_text="Select the type of article.",
|
258
|
+
null=True,
|
259
|
+
on_delete=django.db.models.deletion.SET_NULL,
|
260
|
+
related_name="articles",
|
261
|
+
to="hpk.articletype",
|
262
|
+
),
|
263
|
+
),
|
264
|
+
]
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Generated by Django 5.1.4 on 2024-12-19 22:18
|
2
|
+
|
3
|
+
import wagtail.fields
|
4
|
+
from django.db import migrations
|
5
|
+
|
6
|
+
|
7
|
+
class Migration(migrations.Migration):
|
8
|
+
dependencies = [
|
9
|
+
("hpk", "0001_initial"),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AlterField(
|
14
|
+
model_name="article",
|
15
|
+
name="content",
|
16
|
+
field=wagtail.fields.StreamField(
|
17
|
+
[("section", 5), ("code", 8), ("image", 3)],
|
18
|
+
blank=True,
|
19
|
+
block_lookup={
|
20
|
+
0: (
|
21
|
+
"wagtail.blocks.CharBlock",
|
22
|
+
(),
|
23
|
+
{"help_text": "Heading for this section.", "required": True},
|
24
|
+
),
|
25
|
+
1: (
|
26
|
+
"wagtail.blocks.IntegerBlock",
|
27
|
+
(),
|
28
|
+
{
|
29
|
+
"help_text": "Heading level",
|
30
|
+
"max_value": 6,
|
31
|
+
"min_value": 1,
|
32
|
+
"required": True,
|
33
|
+
},
|
34
|
+
),
|
35
|
+
2: (
|
36
|
+
"wagtail.blocks.RichTextBlock",
|
37
|
+
(),
|
38
|
+
{"features": ["bold", "italic", "link", "ul", "ol", "document-link"]},
|
39
|
+
),
|
40
|
+
3: ("wagtail.images.blocks.ImageChooserBlock", (), {}),
|
41
|
+
4: (
|
42
|
+
"wagtail.blocks.StreamBlock",
|
43
|
+
[[("rich_text", 2), ("image", 3)]],
|
44
|
+
{"help_text": "Content blocks for this section.", "required": False},
|
45
|
+
),
|
46
|
+
5: (
|
47
|
+
"wagtail.blocks.StructBlock",
|
48
|
+
[[("heading", 0), ("level", 1), ("content", 4)]],
|
49
|
+
{},
|
50
|
+
),
|
51
|
+
6: (
|
52
|
+
"wagtail.blocks.TextBlock",
|
53
|
+
(),
|
54
|
+
{"help_text": "Paste your code here.", "required": True},
|
55
|
+
),
|
56
|
+
7: (
|
57
|
+
"wagtail.blocks.ChoiceBlock",
|
58
|
+
[],
|
59
|
+
{
|
60
|
+
"choices": [
|
61
|
+
("python", "Python"),
|
62
|
+
("javascript", "JavaScript"),
|
63
|
+
("html", "HTML"),
|
64
|
+
("css", "CSS"),
|
65
|
+
("bash", "Bash"),
|
66
|
+
("plaintext", "Plain Text"),
|
67
|
+
],
|
68
|
+
"help_text": "Select the language for syntax highlighting.",
|
69
|
+
"required": False,
|
70
|
+
},
|
71
|
+
),
|
72
|
+
8: ("wagtail.blocks.StructBlock", [[("code", 6), ("language", 7)]], {}),
|
73
|
+
},
|
74
|
+
help_text="Main content for the article.",
|
75
|
+
),
|
76
|
+
),
|
77
|
+
migrations.AlterField(
|
78
|
+
model_name="basicpage",
|
79
|
+
name="content",
|
80
|
+
field=wagtail.fields.StreamField(
|
81
|
+
[("rich_text", 0), ("code", 3), ("image", 4)],
|
82
|
+
blank=True,
|
83
|
+
block_lookup={
|
84
|
+
0: ("wagtail.blocks.RichTextBlock", (), {}),
|
85
|
+
1: (
|
86
|
+
"wagtail.blocks.TextBlock",
|
87
|
+
(),
|
88
|
+
{"help_text": "Paste your code here.", "required": True},
|
89
|
+
),
|
90
|
+
2: (
|
91
|
+
"wagtail.blocks.ChoiceBlock",
|
92
|
+
[],
|
93
|
+
{
|
94
|
+
"choices": [
|
95
|
+
("python", "Python"),
|
96
|
+
("javascript", "JavaScript"),
|
97
|
+
("html", "HTML"),
|
98
|
+
("css", "CSS"),
|
99
|
+
("bash", "Bash"),
|
100
|
+
("plaintext", "Plain Text"),
|
101
|
+
],
|
102
|
+
"help_text": "Select the language for syntax highlighting.",
|
103
|
+
"required": False,
|
104
|
+
},
|
105
|
+
),
|
106
|
+
3: ("wagtail.blocks.StructBlock", [[("code", 1), ("language", 2)]], {}),
|
107
|
+
4: ("wagtail.images.blocks.ImageChooserBlock", (), {}),
|
108
|
+
},
|
109
|
+
help_text="Main content for the page.",
|
110
|
+
),
|
111
|
+
),
|
112
|
+
]
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Generated by Django 5.1.4 on 2024-12-19 22:21
|
2
|
+
|
3
|
+
import wagtail.fields
|
4
|
+
from django.db import migrations
|
5
|
+
|
6
|
+
|
7
|
+
class Migration(migrations.Migration):
|
8
|
+
dependencies = [
|
9
|
+
("hpk", "0002_alter_article_content_alter_basicpage_content"),
|
10
|
+
]
|
11
|
+
|
12
|
+
operations = [
|
13
|
+
migrations.AlterField(
|
14
|
+
model_name="article",
|
15
|
+
name="content",
|
16
|
+
field=wagtail.fields.StreamField(
|
17
|
+
[("section", 5), ("code", 8), ("image", 3)],
|
18
|
+
blank=True,
|
19
|
+
block_lookup={
|
20
|
+
0: (
|
21
|
+
"wagtail.blocks.CharBlock",
|
22
|
+
(),
|
23
|
+
{"help_text": "Heading for this section.", "required": True},
|
24
|
+
),
|
25
|
+
1: (
|
26
|
+
"wagtail.blocks.IntegerBlock",
|
27
|
+
(),
|
28
|
+
{
|
29
|
+
"help_text": "Heading level",
|
30
|
+
"max_value": 6,
|
31
|
+
"min_value": 1,
|
32
|
+
"required": True,
|
33
|
+
},
|
34
|
+
),
|
35
|
+
2: (
|
36
|
+
"wagtail.blocks.RichTextBlock",
|
37
|
+
(),
|
38
|
+
{"features": ["bold", "italic", "link", "ul", "ol", "document-link"]},
|
39
|
+
),
|
40
|
+
3: ("wagtail.images.blocks.ImageChooserBlock", (), {}),
|
41
|
+
4: (
|
42
|
+
"wagtail.blocks.StreamBlock",
|
43
|
+
[[("rich_text", 2), ("image", 3)]],
|
44
|
+
{"help_text": "Content blocks for this section.", "required": False},
|
45
|
+
),
|
46
|
+
5: (
|
47
|
+
"wagtail.blocks.StructBlock",
|
48
|
+
[[("heading", 0), ("level", 1), ("content", 4)]],
|
49
|
+
{},
|
50
|
+
),
|
51
|
+
6: ("wagtail.blocks.TextBlock", (), {"help_text": None, "required": True}),
|
52
|
+
7: (
|
53
|
+
"wagtail.blocks.ChoiceBlock",
|
54
|
+
[],
|
55
|
+
{
|
56
|
+
"choices": [
|
57
|
+
("python", "Python"),
|
58
|
+
("javascript", "JavaScript"),
|
59
|
+
("html", "HTML"),
|
60
|
+
("css", "CSS"),
|
61
|
+
("bash", "Bash"),
|
62
|
+
("plaintext", "Plain Text"),
|
63
|
+
],
|
64
|
+
"help_text": "Select the language for syntax highlighting.",
|
65
|
+
"required": False,
|
66
|
+
},
|
67
|
+
),
|
68
|
+
8: ("wagtail.blocks.StructBlock", [[("code", 6), ("language", 7)]], {}),
|
69
|
+
},
|
70
|
+
help_text="Main content for the article.",
|
71
|
+
),
|
72
|
+
),
|
73
|
+
migrations.AlterField(
|
74
|
+
model_name="basicpage",
|
75
|
+
name="content",
|
76
|
+
field=wagtail.fields.StreamField(
|
77
|
+
[("rich_text", 0), ("code", 3), ("image", 4)],
|
78
|
+
blank=True,
|
79
|
+
block_lookup={
|
80
|
+
0: ("wagtail.blocks.RichTextBlock", (), {}),
|
81
|
+
1: ("wagtail.blocks.TextBlock", (), {"help_text": None, "required": True}),
|
82
|
+
2: (
|
83
|
+
"wagtail.blocks.ChoiceBlock",
|
84
|
+
[],
|
85
|
+
{
|
86
|
+
"choices": [
|
87
|
+
("python", "Python"),
|
88
|
+
("javascript", "JavaScript"),
|
89
|
+
("html", "HTML"),
|
90
|
+
("css", "CSS"),
|
91
|
+
("bash", "Bash"),
|
92
|
+
("plaintext", "Plain Text"),
|
93
|
+
],
|
94
|
+
"help_text": "Select the language for syntax highlighting.",
|
95
|
+
"required": False,
|
96
|
+
},
|
97
|
+
),
|
98
|
+
3: ("wagtail.blocks.StructBlock", [[("code", 1), ("language", 2)]], {}),
|
99
|
+
4: ("wagtail.images.blocks.ImageChooserBlock", (), {}),
|
100
|
+
},
|
101
|
+
help_text="Main content for the page.",
|
102
|
+
),
|
103
|
+
),
|
104
|
+
]
|