wagtail-block-fields 0.1.0__tar.gz

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.
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v4
15
+ - run: uv sync
16
+ - run: uv run ruff check .
17
+ - run: uv run ruff format --check .
18
+
19
+ test:
20
+ runs-on: ubuntu-latest
21
+ strategy:
22
+ matrix:
23
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
24
+ wagtail-version: ["6.3", "7.2"]
25
+ include:
26
+ - wagtail-version: "6.3"
27
+ django-version: "5.1"
28
+ - wagtail-version: "7.2"
29
+ django-version: "5.2"
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ - uses: astral-sh/setup-uv@v4
33
+ with:
34
+ python-version: ${{ matrix.python-version }}
35
+ - run: uv sync
36
+ - run: uv add django==${{ matrix.django-version }} wagtail==${{ matrix.wagtail-version }}
37
+ - run: uv run pytest tests/
@@ -0,0 +1,29 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ id-token: write
9
+
10
+ jobs:
11
+ publish:
12
+ runs-on: ubuntu-latest
13
+ environment: pypi
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.11"
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v4
24
+
25
+ - name: Build package
26
+ run: uv build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,191 @@
1
+ # Wagtail test uploads
2
+ original_images/
3
+ images/
4
+ documents/
5
+
6
+
7
+ # General
8
+ .DS_Store
9
+ .AppleDouble
10
+ .LSOverride
11
+
12
+ # Icon must end with two \r
13
+ Icon
14
+
15
+
16
+ # Thumbnails
17
+ ._*
18
+
19
+ # Files that might appear in the root of a volume
20
+ .DocumentRevisions-V100
21
+ .fseventsd
22
+ .Spotlight-V100
23
+ .TemporaryItems
24
+ .Trashes
25
+ .VolumeIcon.icns
26
+ .com.apple.timemachine.donotpresent
27
+
28
+ # Directories potentially created on remote AFP share
29
+ .AppleDB
30
+ .AppleDesktop
31
+ Network Trash Folder
32
+ Temporary Items
33
+ .apdisk
34
+
35
+ # Byte-compiled / optimized / DLL files
36
+ __pycache__/
37
+ *.py[cod]
38
+ *$py.class
39
+
40
+ # C extensions
41
+ *.so
42
+
43
+ # Distribution / packaging
44
+ .Python
45
+ build/
46
+ develop-eggs/
47
+ dist/
48
+ downloads/
49
+ eggs/
50
+ .eggs/
51
+ lib/
52
+ lib64/
53
+ parts/
54
+ sdist/
55
+ var/
56
+ wheels/
57
+ share/python-wheels/
58
+ *.egg-info/
59
+ .installed.cfg
60
+ *.egg
61
+ MANIFEST
62
+
63
+ # PyInstaller
64
+ # Usually these files are written by a python script from a template
65
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
66
+ *.manifest
67
+ *.spec
68
+
69
+ # Installer logs
70
+ pip-log.txt
71
+ pip-delete-this-directory.txt
72
+
73
+ # Unit test / coverage reports
74
+ htmlcov/
75
+ .tox/
76
+ .nox/
77
+ .coverage
78
+ .coverage.*
79
+ .*cache
80
+ nosetests.xml
81
+ coverage.xml
82
+ *.cover
83
+ *.py,cover
84
+ .hypothesis/
85
+ .pytest_cache/
86
+ cover/
87
+ pytest.xml
88
+ pytest-coverage.txt
89
+
90
+ # Translations
91
+ *.mo
92
+ *.pot
93
+
94
+ # Django stuff:
95
+ *.log
96
+ local_settings.py
97
+ db.sqlite3
98
+ db.sqlite3-journal
99
+
100
+ # Flask stuff:
101
+ instance/
102
+ .webassets-cache
103
+
104
+ # Scrapy stuff:
105
+ .scrapy
106
+
107
+ # Sphinx documentation
108
+ docs/_build/
109
+
110
+ # PyBuilder
111
+ .pybuilder/
112
+ target/
113
+
114
+ # Jupyter Notebook
115
+ .ipynb_checkpoints
116
+
117
+ # IPython
118
+ profile_default/
119
+ ipython_config.py
120
+
121
+ # pyenv
122
+ # For a library or package, you might want to ignore these files since the code is
123
+ # intended to run in multiple environments; otherwise, check them in:
124
+ # .python-version
125
+
126
+ # pipenv
127
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
128
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
129
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
130
+ # install all needed dependencies.
131
+ #Pipfile.lock
132
+
133
+ # poetry
134
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
135
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
136
+ # commonly ignored for libraries.
137
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
138
+ #poetry.lock
139
+
140
+ # pdm
141
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
142
+ #pdm.lock
143
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
144
+ # in version control.
145
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
146
+ .pdm.toml
147
+ .pdm-python
148
+ .pdm-build/
149
+
150
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
151
+ __pypackages__/
152
+
153
+ # Celery stuff
154
+ celerybeat-schedule
155
+ celerybeat.pid
156
+
157
+ # SageMath parsed files
158
+ *.sage.py
159
+
160
+ # Environments
161
+ .env
162
+ .venv
163
+ env/
164
+ venv/
165
+ ENV/
166
+ env.bak/
167
+ venv.bak/
168
+
169
+ # Spyder project settings
170
+ .spyderproject
171
+ .spyproject
172
+
173
+ # Rope project settings
174
+ .ropeproject
175
+
176
+ # mkdocs documentation
177
+ /site
178
+
179
+ # mypy
180
+ .mypy_cache/
181
+ .dmypy.json
182
+ dmypy.json
183
+
184
+ # Pyre type checker
185
+ .pyre/
186
+
187
+ # pytype static type analyzer
188
+ .pytype/
189
+
190
+ # Cython debug symbols
191
+ cython_debug/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Joey Jurjens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: wagtail-block-fields
3
+ Version: 0.1.0
4
+ Summary: Allows using StructBlock and ListBlock as model fields
5
+ Project-URL: Repository, https://github.com/joeyjurjens/wagtail-block-fields
6
+ Author-email: Joey Jurjens <joeyjurjens@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Requires-Python: >=3.10
10
+ Requires-Dist: wagtail>=6.3
11
+ Description-Content-Type: text/markdown
12
+
13
+ # wagtail-block-fields
14
+
15
+ Use Wagtail's `StructBlock` and `ListBlock` as standalone model fields.
16
+
17
+ Just like `StreamField` wraps `StreamBlock`, this package provides:
18
+ - **`StructField`** - wraps a `StructBlock`
19
+ - **`ListField`** - wraps a `ListBlock`
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ pip install wagtail-block-fields
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### StructField
30
+
31
+ ```python
32
+ from wagtail.blocks import CharBlock, StructBlock
33
+ from wagtail_block_fields import StructField
34
+
35
+ class AddressBlock(StructBlock):
36
+ street = CharBlock()
37
+ city = CharBlock()
38
+ postal_code = CharBlock()
39
+
40
+ class MyPage(Page):
41
+ address = StructField(AddressBlock())
42
+
43
+ contact = StructField([
44
+ ('email', CharBlock()),
45
+ ('phone', CharBlock()),
46
+ ])
47
+ ```
48
+
49
+ ### ListField
50
+
51
+ ```python
52
+ from wagtail.blocks import CharBlock
53
+ from wagtail_block_fields import ListField
54
+
55
+ class MyPage(Page):
56
+ tags = ListField(CharBlock())
57
+ categories = ListField(CharBlock(), min_num=1, max_num=5)
58
+ addresses = ListField(AddressBlock())
59
+ ```
60
+
61
+ ### In templates
62
+
63
+ ```html
64
+ <p>{{ page.address.street }}, {{ page.address.city }}</p>
65
+
66
+ <ul>
67
+ {% for tag in page.tags %}
68
+ <li>{{ tag }}</li>
69
+ {% endfor %}
70
+ </ul>
71
+
72
+ {% for address in page.addresses %}
73
+ <p>{{ address.street }}, {{ address.city }}</p>
74
+ {% endfor %}
75
+ ```
76
+
77
+ ## Why?
78
+
79
+ Sometimes you need structured JSON data in a single field without the complexity of StreamField. These fields:
80
+
81
+ - Store data as JSON in a single database column
82
+ - Provide full Wagtail admin editing UI
83
+ - Support validation, search indexing, and reference extraction
84
+ - Work with migrations just like StreamField
85
+
86
+ ## License
87
+
88
+ MIT
@@ -0,0 +1,76 @@
1
+ # wagtail-block-fields
2
+
3
+ Use Wagtail's `StructBlock` and `ListBlock` as standalone model fields.
4
+
5
+ Just like `StreamField` wraps `StreamBlock`, this package provides:
6
+ - **`StructField`** - wraps a `StructBlock`
7
+ - **`ListField`** - wraps a `ListBlock`
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install wagtail-block-fields
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### StructField
18
+
19
+ ```python
20
+ from wagtail.blocks import CharBlock, StructBlock
21
+ from wagtail_block_fields import StructField
22
+
23
+ class AddressBlock(StructBlock):
24
+ street = CharBlock()
25
+ city = CharBlock()
26
+ postal_code = CharBlock()
27
+
28
+ class MyPage(Page):
29
+ address = StructField(AddressBlock())
30
+
31
+ contact = StructField([
32
+ ('email', CharBlock()),
33
+ ('phone', CharBlock()),
34
+ ])
35
+ ```
36
+
37
+ ### ListField
38
+
39
+ ```python
40
+ from wagtail.blocks import CharBlock
41
+ from wagtail_block_fields import ListField
42
+
43
+ class MyPage(Page):
44
+ tags = ListField(CharBlock())
45
+ categories = ListField(CharBlock(), min_num=1, max_num=5)
46
+ addresses = ListField(AddressBlock())
47
+ ```
48
+
49
+ ### In templates
50
+
51
+ ```html
52
+ <p>{{ page.address.street }}, {{ page.address.city }}</p>
53
+
54
+ <ul>
55
+ {% for tag in page.tags %}
56
+ <li>{{ tag }}</li>
57
+ {% endfor %}
58
+ </ul>
59
+
60
+ {% for address in page.addresses %}
61
+ <p>{{ address.street }}, {{ address.city }}</p>
62
+ {% endfor %}
63
+ ```
64
+
65
+ ## Why?
66
+
67
+ Sometimes you need structured JSON data in a single field without the complexity of StreamField. These fields:
68
+
69
+ - Store data as JSON in a single database column
70
+ - Provide full Wagtail admin editing UI
71
+ - Support validation, search indexing, and reference extraction
72
+ - Work with migrations just like StreamField
73
+
74
+ ## License
75
+
76
+ MIT
@@ -0,0 +1,57 @@
1
+ [project]
2
+ name = "wagtail-block-fields"
3
+ version = "0.1.0"
4
+ description = "Allows using StructBlock and ListBlock as model fields"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Joey Jurjens", email = "joeyjurjens@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.10"
10
+ license = "MIT"
11
+ dependencies = [
12
+ "wagtail>=6.3",
13
+ ]
14
+
15
+ [project.urls]
16
+ Repository = "https://github.com/joeyjurjens/wagtail-block-fields"
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["wagtail_block_fields"]
24
+
25
+ [tool.pytest.ini_options]
26
+ DJANGO_SETTINGS_MODULE = "tests.settings"
27
+ pythonpath = ["."]
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "pytest>=8.4.2",
32
+ "pytest-django>=4.11.1",
33
+ "ruff>=0.8.0",
34
+ ]
35
+
36
+ [tool.ruff]
37
+ line-length = 100
38
+ target-version = "py39"
39
+
40
+ [tool.ruff.lint]
41
+ select = ["E", "F", "I", "UP", "B", "SIM"]
42
+
43
+ [tool.ruff.lint.isort]
44
+ known-first-party = ["wagtail_block_fields"]
45
+ section-order = [
46
+ "future",
47
+ "standard-library",
48
+ "django",
49
+ "wagtail",
50
+ "third-party",
51
+ "first-party",
52
+ "local-folder",
53
+ ]
54
+
55
+ [tool.ruff.lint.isort.sections]
56
+ django = ["django", "django_*"]
57
+ wagtail = ["wagtail", "wagtail_*"]
File without changes
@@ -0,0 +1,29 @@
1
+ SECRET_KEY = "test-secret-key-not-for-production"
2
+
3
+ INSTALLED_APPS = [
4
+ "django.contrib.contenttypes",
5
+ "django.contrib.auth",
6
+ "taggit",
7
+ "wagtail.users",
8
+ "wagtail.images",
9
+ "wagtail.search",
10
+ "wagtail.documents",
11
+ "wagtail.admin",
12
+ "wagtail",
13
+ "tests.testapp",
14
+ ]
15
+
16
+ DATABASES = {
17
+ "default": {
18
+ "ENGINE": "django.db.backends.sqlite3",
19
+ "NAME": ":memory:",
20
+ }
21
+ }
22
+
23
+ USE_TZ = True
24
+
25
+ WAGTAIL_SITE_NAME = "Test"
26
+
27
+ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
28
+
29
+ STATIC_URL = "/static/"