├── .circleci └── config.yml ├── .github └── workflows │ └── test.yaml ├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs ├── CONTRIBUTING.md └── images │ ├── create.png │ └── dashboard.png ├── runtests.py ├── setup.cfg ├── setup.py └── wagtailquickcreate ├── __init__.py ├── templates └── wagtailquickcreate │ ├── create.html │ └── panel.html ├── tests ├── __init__.py ├── fixtures │ └── test.json ├── settings.py ├── standardpages │ ├── __init__.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ └── models.py ├── tests.py └── urls.py ├── views.py └── wagtail_hooks.py /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/wagtailquickcreate 5 | docker: 6 | - image: circleci/python:3.8.0 7 | environment: 8 | PIPENV_VENV_IN_PROJECT: true 9 | DATABASE_URL: postgresql://root@localhost/circle_test?sslmode=disable 10 | - image: circleci/postgres:9.6.2 11 | environment: 12 | POSTGRES_USER: root 13 | POSTGRES_DB: circle_test 14 | steps: 15 | - checkout 16 | - run: sudo chown -R circleci:circleci /usr/local/bin 17 | - run: sudo chown -R circleci:circleci /usr/local/lib/python3.8/site-packages 18 | - run: 19 | command: | 20 | sudo pip install pipenv 21 | pipenv install wagtail 22 | - run: 23 | command: | 24 | pipenv run python runtests.py 25 | - store_test_results: 26 | path: test-results 27 | - store_artifacts: 28 | path: test-results 29 | destination: tr1 30 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Python testing 2 | 3 | on: 4 | push: 5 | pull_request: 6 | branches: [master] 7 | 8 | jobs: 9 | test: 10 | name: Test 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | include: 15 | - python: 3.9 16 | wagtail: wagtail>=4.1 17 | steps: 18 | - uses: actions/checkout@v3 19 | - uses: actions/setup-python@v3 20 | with: 21 | python-version: ${{ matrix.python }} 22 | cache: "pip" 23 | cache-dependency-path: "**/setup.cfg" 24 | - run: | 25 | pip install "${{ matrix.wagtail }}" 26 | - run: | 27 | python runtests.py 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | *.egg-info 4 | build/ 5 | dist/ 6 | .tox/ 7 | Pipfile 8 | venv 9 | testapp 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Kevin 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. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include wagtailquickcreate/templates * 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wagtail Quick Create 2 | 3 | ## Wagtail Quick Create offers shortcut links to create objects from models specified in your settings file. 4 | 5 | A panel is added to the admin home, offering a type: 6 | 7 | ![Quick Create Panel example](./docs/images/dashboard.png) 8 | 9 | Clicking a create link will offer a parent selection for the new item 10 | 11 | ![Parent selection example](./docs/images/create.png) 12 | 13 | ## Note on parent pages 14 | 15 | Wagtailquickcreate needs the [`parent_page_types`](http://docs.wagtail.io/en/v2.5.1/reference/pages/model_reference.html#wagtail.core.models.Page.parent_page_types) set on the model you wish to include so it can successfully provide the parent page selection. If this isn't specified, you will likely see every page offered as a parent, this will not work as it's looking up pages using `wagtail.core.models.Page` and this core wagtail class has `is_creatable = False` 16 | 17 | ### Configuration 18 | 19 | Install using pip: 20 | 21 | ```bash 22 | pip install wagtail-quick-create 23 | ``` 24 | 25 | After installing the module, add `wagtailquickcreate` to your installed apps in your settings file: 26 | 27 | ```python 28 | INSTALLED_APPS = [ 29 | ... 30 | 'wagtailquickcreate', 31 | ] 32 | ``` 33 | 34 | Also add the models you would like to create quick links for to your settings file as `'your_app_name.YourModelName'`: 35 | 36 | EG: 37 | 38 | ```python 39 | WAGTAIL_QUICK_CREATE_PAGE_TYPES = ['news.NewsPage', 'events.EventPage'] 40 | ``` 41 | 42 | If you want the Quick Create links panel to _replace_ the wagtail summary panel, you can set this by adding the following to your settings 43 | 44 | ```python 45 | WAGTAIL_QUICK_CREATE_REPLACE_SUMMARY_PANEL = True 46 | ``` 47 | 48 | If you would like to offer image and or document links, this can also be done by specifying the following in your settings: 49 | 50 | ```python 51 | WAGTAIL_QUICK_CREATE_DOCUMENTS = True 52 | WAGTAIL_QUICK_CREATE_IMAGES = True 53 | ``` 54 | 55 | ## Contributing 56 | 57 | We are happy to receive pull requests for bug fixes, improvements and new features. See [CONTRIBUTING.md](./docs/CONTRIBUTING.md) for more information. 58 | 59 | ## Credits/Authors 60 | 61 | Concept created by Kate Statton - NYPR [@katestatton](https://twitter.com/katestatton) 62 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We are happy to receive pull requests for bug fixes, improvements and new features. 4 | 5 | ## Developer setup 6 | 7 | ### Clone the repository ⤵️ 8 | 9 | ```bash 10 | git clone https://github.com/torchbox/wagtailquickcreate 11 | ``` 12 | 13 | ### Create a virtualenv and install the requirements 🐍 14 | 15 | ```bash 16 | cd wagtailquickcreate 17 | python3 -m venv venv 18 | source venv/bin/activate 19 | pip install -e . 20 | ``` 21 | 22 | ### Run the tests 🧪 23 | 24 | ```bash 25 | python runtests.py 26 | ``` 27 | 28 | ## Pull requests 🙏 29 | 30 | Your pull request should include: 31 | 32 | - A description of the changes proposed in the pull request 33 | - Tests for new features. 34 | - Documentation update for new features. 35 | 36 | Submit your pull request here: https://github.com/torchbox/wagtailquickcreate/pulls 37 | -------------------------------------------------------------------------------- /docs/images/create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/wagtailquickcreate/e9d4c1b13ccdbb47abcbf78b015bae667a670519/docs/images/create.png -------------------------------------------------------------------------------- /docs/images/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/wagtailquickcreate/e9d4c1b13ccdbb47abcbf78b015bae667a670519/docs/images/dashboard.png -------------------------------------------------------------------------------- /runtests.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import sys 4 | 5 | from django.core.management import execute_from_command_line 6 | 7 | os.environ['DJANGO_SETTINGS_MODULE'] = 'wagtailquickcreate.tests.settings' 8 | execute_from_command_line([sys.argv[0], 'test']) 9 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [flake8] 5 | ignore = C901,W503 6 | exclude = */migrations/*,*/node_modules/* 7 | max-line-length = 120 8 | 9 | [isort] 10 | known_first_party=wagtailautocreate 11 | known_django=django 12 | known_wagtail=wagtail,modelcluster 13 | skip=migrations,node_modules,venv 14 | sections=STDLIB,DJANGO,WAGTAIL,THIRDPARTY,FIRSTPARTY,LOCALFOLDER 15 | default_section=THIRDPARTY 16 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Installs the Wagtail Quick Create plugin which offers shortcut links on the admin 4 | home screen to create defined pages under parent pages. 5 | """ 6 | 7 | from os import path 8 | 9 | from setuptools import find_packages, setup 10 | 11 | this_directory = path.abspath(path.dirname(__file__)) 12 | with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: 13 | long_description = f.read() 14 | 15 | 16 | setup( 17 | name='wagtail-quick-create', 18 | version='2.0.2', 19 | description='Offer links to the admin user to create content under sections quickly.', 20 | long_description=long_description, 21 | long_description_content_type='text/markdown', 22 | url='https://github.com/kevinhowbrook/wagtailquickcreate', 23 | author='Kevin Howbrook - Torchbox, Kate Statton - NYPR', 24 | author_email='kevin.howbrook@torchbox.com', 25 | license='MIT', 26 | packages=find_packages(exclude=['tests*']), 27 | include_package_data=True, 28 | install_requires=[ 29 | 'wagtail>=4.1', 30 | ], 31 | classifiers=[ 32 | 'Environment :: Web Environment', 33 | 'Intended Audience :: Developers', 34 | 'Operating System :: OS Independent', 35 | 'Programming Language :: Python', 36 | 'Programming Language :: Python :: 3', 37 | 'Programming Language :: Python :: 3.8', 38 | 'Programming Language :: Python :: 3.9', 39 | 'Programming Language :: Python :: 3.10', 40 | 'Programming Language :: Python :: 3.11', 41 | 'Programming Language :: Python :: 3.12', 42 | 'Framework :: Wagtail', 43 | 'Framework :: Wagtail :: 4', 44 | 'Framework :: Wagtail :: 5', 45 | ], 46 | ) 47 | -------------------------------------------------------------------------------- /wagtailquickcreate/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/wagtailquickcreate/e9d4c1b13ccdbb47abcbf78b015bae667a670519/wagtailquickcreate/__init__.py -------------------------------------------------------------------------------- /wagtailquickcreate/templates/wagtailquickcreate/create.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "wagtailadmin/base.html" %} 3 | {% load wagtailadmin_tags static i18n %} 4 | {% block titletag %}{% trans browser_title %}{% endblock %} 5 | 6 | 7 | {% block content %} 8 |
9 |
10 |
11 |

12 | 13 | Add {{ model_verbose_name }} 14 |

15 |

{{ user.get_full_name|default:user.get_username }}

16 |
17 |
18 |
19 |
20 | 42 |
43 | 44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /wagtailquickcreate/templates/wagtailquickcreate/panel.html: -------------------------------------------------------------------------------- 1 |
2 | {{ models }} 3 |
-------------------------------------------------------------------------------- /wagtailquickcreate/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/wagtailquickcreate/e9d4c1b13ccdbb47abcbf78b015bae667a670519/wagtailquickcreate/tests/__init__.py -------------------------------------------------------------------------------- /wagtailquickcreate/tests/fixtures/test.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "model": "auth.user", 4 | "pk": 1, 5 | "fields": { 6 | "password": "pbkdf2_sha256$120000$0MlJbgNt3EXM$wP4KSUIZ/HCFYnG1Z/ZsadFvnzOAXM42YWyaEz8yuwg=", 7 | "last_login": "2019-04-04T14:36:55.317Z", 8 | "is_superuser": true, 9 | "username": "admin", 10 | "first_name": "", 11 | "last_name": "", 12 | "email": "email@example.com", 13 | "is_staff": true, 14 | "is_active": true, 15 | "date_joined": "2019-04-04T11:53:16.724Z", 16 | "groups": [], 17 | "user_permissions": [] 18 | } 19 | }, 20 | { 21 | "model": "auth.user", 22 | "pk": 2, 23 | "fields": { 24 | "password": "pbkdf2_sha256$120000$DWm3O0jiLofZ$mgF1F11zilg90LYKMvyaydiIZUh11Ulf2cL46NebsXw=", 25 | "last_login": null, 26 | "is_superuser": true, 27 | "username": "user", 28 | "first_name": "", 29 | "last_name": "", 30 | "email": "email@example.com", 31 | "is_staff": true, 32 | "is_active": true, 33 | "date_joined": "2019-04-04T11:53:16.898Z", 34 | "groups": [], 35 | "user_permissions": [] 36 | } 37 | }, 38 | { 39 | "pk": 1, 40 | "model": "wagtailcore.page", 41 | "fields": { 42 | "title": "Root", 43 | "numchild": 1, 44 | "show_in_menus": false, 45 | "live": true, 46 | "depth": 1, 47 | "content_type": [ 48 | "wagtailcore", 49 | "page" 50 | ], 51 | "path": "0001", 52 | "url_path": "/", 53 | "slug": "root" 54 | } 55 | }, 56 | 57 | { 58 | "pk": 2, 59 | "model": "wagtailcore.page", 60 | "fields": { 61 | "title": "Home", 62 | "numchild": 0, 63 | "show_in_menus": false, 64 | "live": true, 65 | "depth": 2, 66 | "content_type": [ 67 | "wagtailcore", 68 | "page" 69 | ], 70 | "path": "00010001", 71 | "url_path": "/home/", 72 | "slug": "home" 73 | } 74 | } 75 | ] -------------------------------------------------------------------------------- /wagtailquickcreate/tests/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 | BASE_DIR = os.path.dirname(PROJECT_DIR) 5 | 6 | 7 | SECRET_KEY = 'not so secret' 8 | 9 | DATABASES = { 10 | 'default': { 11 | 'ENGINE': 'django.db.backends.sqlite3', 12 | 'NAME': 'db.sqlite3', 13 | } 14 | } 15 | 16 | INSTALLED_APPS = [ 17 | 18 | 'wagtail.contrib.styleguide', 19 | 'wagtail.contrib.routable_page', 20 | 'wagtail.contrib.frontend_cache', 21 | 'wagtail.contrib.settings', 22 | 'wagtail.contrib.table_block', 23 | 'wagtail.contrib.forms', 24 | 'wagtail.embeds', 25 | 'wagtail.sites', 26 | 'wagtail.users', 27 | 'wagtail.snippets', 28 | 'wagtail.documents', 29 | 'wagtail.images', 30 | 'wagtail.admin', 31 | "wagtail", 32 | 33 | 'taggit', 34 | 35 | 'django.contrib.admin', 36 | 'django.contrib.auth', 37 | 'django.contrib.contenttypes', 38 | 'django.contrib.sessions', 39 | 'django.contrib.messages', 40 | 'django.contrib.sitemaps', 41 | 'wagtailquickcreate', 42 | 'wagtailquickcreate.tests.standardpages', 43 | 44 | ] 45 | 46 | 47 | MIDDLEWARE = [ 48 | 'django.contrib.sessions.middleware.SessionMiddleware', 49 | 'django.middleware.common.CommonMiddleware', 50 | 'django.middleware.csrf.CsrfViewMiddleware', 51 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 52 | 'django.contrib.messages.middleware.MessageMiddleware', 53 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 54 | ] 55 | 56 | ROOT_URLCONF = 'wagtailquickcreate.tests.urls' 57 | 58 | TEMPLATES = [ 59 | { 60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 61 | 'APP_DIRS': True, 62 | 'OPTIONS': { 63 | 'context_processors': [ 64 | 'django.template.context_processors.debug', 65 | 'django.template.context_processors.request', 66 | 'django.contrib.auth.context_processors.auth', 67 | 'django.contrib.messages.context_processors.messages', 68 | 'wagtail.contrib.settings.context_processors.settings', 69 | ], 70 | }, 71 | }, 72 | ] 73 | 74 | WAGTAIL_SITE_NAME = 'llama-savers' 75 | WAGTAIL_QUICK_CREATE_REPLACE_SUMMARY_PANEL = True 76 | WAGTAIL_QUICK_CREATE_DOCUMENTS = True 77 | WAGTAIL_QUICK_CREATE_IMAGES = True 78 | WAGTAIL_QUICK_CREATE_PAGE_TYPES = ['wagtailquickcreate.tests.standardpages.InformationPage'] 79 | USE_TZ = True 80 | 81 | WAGTAILADMIN_BASE_URL = 'http://localhost:8000' 82 | 83 | STATIC_URL = "/static/" 84 | -------------------------------------------------------------------------------- /wagtailquickcreate/tests/standardpages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/wagtailquickcreate/e9d4c1b13ccdbb47abcbf78b015bae667a670519/wagtailquickcreate/tests/standardpages/__init__.py -------------------------------------------------------------------------------- /wagtailquickcreate/tests/standardpages/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ('wagtaildocs', '0007_merge'), 12 | ('wagtailcore', '0032_add_bulk_delete_page_permission'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='IndexPage', 18 | fields=[ 19 | ('introduction', models.TextField(blank=True)), 20 | ], 21 | options={ 22 | 'abstract': False, 23 | }, 24 | bases=('wagtailcore.page', models.Model), 25 | ), 26 | migrations.CreateModel( 27 | name='InformationPage', 28 | fields=[ 29 | ('introduction', models.TextField(blank=True)), 30 | ], 31 | options={ 32 | 'abstract': False, 33 | }, 34 | bases=('wagtailcore.page', models.Model), 35 | ), 36 | ] 37 | -------------------------------------------------------------------------------- /wagtailquickcreate/tests/standardpages/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torchbox/wagtailquickcreate/e9d4c1b13ccdbb47abcbf78b015bae667a670519/wagtailquickcreate/tests/standardpages/migrations/__init__.py -------------------------------------------------------------------------------- /wagtailquickcreate/tests/standardpages/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | from wagtail.models import Page 4 | 5 | 6 | class InformationPage(Page): 7 | parent_page_types = ['standardpages.IndexPage'] 8 | 9 | introduction = models.TextField(blank=True) 10 | 11 | 12 | class IndexPage(Page): 13 | 14 | introduction = models.TextField(blank=True) 15 | -------------------------------------------------------------------------------- /wagtailquickcreate/tests/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.urls import reverse 3 | 4 | from wagtail.models import Page 5 | from wagtail.test.utils import WagtailTestUtils 6 | 7 | from wagtailquickcreate.tests.standardpages.models import IndexPage 8 | 9 | 10 | class WagtailQuickCreateTests(TestCase, WagtailTestUtils): 11 | fixtures = ['wagtailquickcreate/tests/fixtures/test.json'] 12 | 13 | def setUp(self): 14 | super().setUp() 15 | self.login() 16 | self.home = Page.objects.get(pk=2) 17 | self.index = IndexPage( 18 | title='Section 1', 19 | slug='section-1', 20 | introduction='...' 21 | ) 22 | self.index_2 = IndexPage( 23 | title='Section 2', 24 | slug='section-2', 25 | introduction='...' 26 | ) 27 | self.home.add_child(instance=self.index) 28 | self.index.add_child(instance=self.index_2) 29 | 30 | def test_admin(self): 31 | response = self.client.get(reverse('wagtailadmin_home')) 32 | self.assertEqual(response.status_code, 200) 33 | 34 | def test_quickcreate_panel_links(self): 35 | response = self.client.get('/admin/') 36 | self.assertTrue('Add Image' in str(response.content)) 37 | self.assertTrue('Add Document' in str(response.content)) 38 | self.assertTrue('Add Information page' in str(response.content)) 39 | 40 | def test_first_level_index_page_in_shortcut_view(self): 41 | response = self.client.get('/admin/quickcreate/create/standardpages/informationpage/') 42 | self.assertContains(response, 'Home > Section 1', html=True) 43 | 44 | def test_second_level_index_in_shortcut_view(self): 45 | response = self.client.get('/admin/quickcreate/create/standardpages/informationpage/') 46 | self.assertContains(response, 'Home > Section 1 > Section 2', html=True) 47 | -------------------------------------------------------------------------------- /wagtailquickcreate/tests/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | 4 | from wagtail.admin import urls as wagtailadmin_urls 5 | 6 | from wagtail import urls as wagtail_urls 7 | 8 | from wagtail.documents import urls as wagtaildocs_urls 9 | 10 | private_urlpatterns = [ 11 | path('django-admin/', admin.site.urls), 12 | path('admin/', include(wagtailadmin_urls)), 13 | path('documents/', include(wagtaildocs_urls)), 14 | ] 15 | 16 | # Public URLs that are meant to be cached. 17 | urlpatterns = [] 18 | 19 | urlpatterns = private_urlpatterns + urlpatterns + [ 20 | # Add Wagtail URLs at the end. 21 | # Wagtail cache-control is set on the page models's serve methods. 22 | path('', include(wagtail_urls)), 23 | ] 24 | -------------------------------------------------------------------------------- /wagtailquickcreate/views.py: -------------------------------------------------------------------------------- 1 | from django.apps import apps 2 | from django.views.generic import TemplateView 3 | 4 | from wagtail.models import Page 5 | 6 | 7 | # Helper function to work out page permissions 8 | def filter_pages_by_permission(user, pages): 9 | return [ 10 | page for page in pages 11 | if page.permissions_for_user(user).can_add_subpage() 12 | ] 13 | 14 | 15 | class QuickCreateView(TemplateView): 16 | template_name = "wagtailquickcreate/create.html" 17 | 18 | def get_context_data(self, **kwargs): 19 | context = super().get_context_data(**kwargs) 20 | 21 | # Work out the parent pages to offer to the user to add 22 | # their new page under, for this we need to query the objects/models 23 | # allowed parent pages 24 | _model = kwargs.pop('model') 25 | app = kwargs.pop('app') 26 | model = apps.get_model(app, _model) 27 | # Exclude base wagtail page class from possible parents 28 | parent_models = [m for m in model.allowed_parent_page_models() if m is not Page] 29 | 30 | # With the 'allowed parent page' models we have found, get all 31 | # those objects from the database so we can offer them as parent pages 32 | # for the new child page being added 33 | self.pages = [] 34 | for pm in parent_models: 35 | for object in pm.objects.all(): 36 | self.pages.append(object) 37 | 38 | # Check the current user has permission to edit pages in question 39 | self.pages = filter_pages_by_permission(self.request.user, self.pages) 40 | 41 | parent_pages = [] 42 | for i in self.pages: 43 | item = {} 44 | item['id'] = i.id 45 | item['title'] = i.title 46 | item['app_label'] = i._meta.app_label 47 | item['model'] = _model 48 | item['page'] = i 49 | # Also send through the section page ancestors for a clearer link path 50 | # to the user. 51 | item['ancestors'] = i.get_ancestors() 52 | parent_pages.append(item) 53 | 54 | context['model_verbose_name'] = model.get_verbose_name() 55 | context['browser_title'] = f'Add a {model.get_verbose_name()}' 56 | context['model_app'] = app 57 | context['parent_pages'] = parent_pages 58 | return context 59 | -------------------------------------------------------------------------------- /wagtailquickcreate/wagtail_hooks.py: -------------------------------------------------------------------------------- 1 | from django.apps import apps 2 | from django.conf import settings 3 | from django.urls import path 4 | from django.utils.safestring import mark_safe 5 | 6 | from wagtail.admin.site_summary import SiteSummaryPanel, SummaryItem 7 | 8 | from wagtail import hooks 9 | 10 | from .views import QuickCreateView 11 | 12 | 13 | class QuickCreatePanel(SummaryItem): 14 | template_name = "wagtailquickcreate/panel.html" 15 | order = 50 16 | 17 | def get_context_data(self, parent_context): 18 | context = super().get_context_data(parent_context) 19 | quick_create_page_types = getattr(settings, "WAGTAIL_QUICK_CREATE_PAGE_TYPES", []) 20 | 21 | if not quick_create_page_types: 22 | return "" 23 | 24 | # Make a list of the models with edit links 25 | # EG [{'link': 'news/NewsPage', 'name': 'News page'}] 26 | page_models = [] 27 | for i in quick_create_page_types: 28 | item = {} 29 | # When testing, or if the app/model has a specific name 30 | # target the last 2 list values 31 | i = i.split('.') 32 | i = '.'.join(i[-2:]) 33 | model = apps.get_model(i) 34 | item['link'] = model._meta.app_label + '/' + model.__name__ 35 | item['name'] = model.get_verbose_name() 36 | page_models.append(item) 37 | 38 | # Build up an html chunk for the links to be rendered in the panel 39 | page_models_html_chunk = [ 40 | """ 41 | 42 | """.format( 47 | model_link=i['link'], model_name=i['name'] 48 | ) 49 | for i in page_models 50 | ] 51 | 52 | page_models_html_chunk = list(set(page_models_html_chunk)) 53 | 54 | if getattr(settings, "WAGTAIL_QUICK_CREATE_IMAGES", False): 55 | page_models_html_chunk.append(""" 56 | 57 | 62 | """) 63 | if getattr(settings, "WAGTAIL_QUICK_CREATE_DOCUMENTS", False): 64 | page_models_html_chunk.append(""" 65 | 66 | 71 | """) 72 | context["models"] = mark_safe(''.join(page_models_html_chunk)) 73 | return context 74 | 75 | 76 | @hooks.register('register_admin_urls') 77 | def urlconf_time(): 78 | # Example: http://127.0.0.1:8000/admin/quickcreate/create/standardpages/InformationPage/ 79 | return [ 80 | path('quickcreate/create///', 81 | QuickCreateView.as_view()), 82 | ] 83 | 84 | 85 | @hooks.register('construct_homepage_panels') 86 | def add_quick_create_panel(request, panels): 87 | # Replace the site summary panel with our custom panel 88 | if getattr(settings, "WAGTAIL_QUICK_CREATE_REPLACE_SUMMARY_PANEL", False): 89 | for i, v in enumerate(panels): 90 | if isinstance(v, SiteSummaryPanel): 91 | panels[i] = QuickCreatePanel(request) 92 | else: 93 | panels.append(QuickCreatePanel(request)) 94 | return panels 95 | --------------------------------------------------------------------------------