Fixes#5983; possibly also has a bearing on #4306. A CSS rule dating from the original StreamField design was hiding the 'required' asterisk on fields within a required StreamField, presumably on the mistaken belief that they duplicate the information given by the top-level asterisk on the streamfield. (In #5983 this was reported as a regression in 2.7 when the react-streamfield CSS was introduced, so it's possible that the old design had something to mitigate this, e.g. an asterisk being inserted elsewhere.)
This fixes#6393 by modifying the constraint to use an IN condition
which supports both Postgres and SQL Server. Previously, the `|` (OR)
condition was only supported by Postgres because SQL Server only
supports AND conditions.
The implementation follows suggestions from @gasman in
https://github.com/wagtail/wagtail/issues/6393#issuecomment-732161057:
* Migration 0050 is modified to not break on SQL Server
* Added migration 0060 to add or replace the constraint
Additionally, this allows for and documents a `DATABASE_DRIVER` env
variable to be set for testing, to allow a different SQL Server driver
(e.g. FreeTDS on Mac/Linux); and adds the specific `host_is_server`
option for FreeTDS (won't affect SQL Server Native Client on CI).
This PR adds the 'choose' permission discussed in #4488. It limits Image and Document choosers to showing only those Collections (and their contents) for which the current user has the Choose permission.
It grants Choose permissions to the Root Collection to every existing Group that has the "Can access Wagtail admin" perm, via data migration. So there will be no change in behavior unless the user goes in and alters the Choose perms for their site's groups.
This PR has no effect on anything except choosers. The Image and Document index pages are still controlled solely by the 'add' and 'change' permissions, as those are only accessible by users who have those permissions in the first place. This means that it's now possible to configure a Group to allow its members to choose images from existing Collections when editing pages, *without* them being able to edit said images or add new ones.
Make sure document chooser pagination preserves the selected collection when moving between pages
Co-authored-by: Alexander Sajzew <a.sajzew@alexsa.de>
Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>
Move code from https://www.codista.com/en/blog/wagtail-instagram-new-oembed-api/ into core
Add custom oembed finder for Facebook
Apply suggestions from @originell's code review
Co-authored-by: Luis Nell <luis.nell@codista.com>
FIXUP More places to change the exception name (and a linter fix)
Extend Instagram/Facebook tests to check HTTP request
Add documentation for omitscript parameter
* Handle get_supported_language_variant returning a language variant not in LANGUAGES
Fixes#6539
* Handle LANGUAGE_CODE that isn't in LANGUAGES
* Release note for #6547
Fixes#6540
There are various code paths where Page.localized and similar can be called even when WAGTAIL_I18N_ENABLED is False, and since it's entirely likely that hand-rolled i18n mechanisms and ad-hoc configuration changes (e.g changing LANGUAGE_CODE) will break the Locale model's assumptions about how things are meant to work, we need to provide sensible fallback behaviour for when the current active locale, or the default locale as per LANGUAGE_CODE, does not have a corresponding Locale record:
* Locale.get_active() will fall back on the default LANGUAGE_CODE locale, or raise Locale.DoesNotExist if that one does not exist either;
* TranslatableMixin.localized (along with Page.localized and Page.localized_draft) will handle a missing Locale record by falling back on the default LANGUAGE_CODE locale, or failing that, returning self.
Fixes#6510 and #6511
Catch the LookupError from get_supported_content_language_variant so that if the active language is not one that is recognised as a content language, the URL prefix will be left unchanged from the page's reported locale.
Additionally, skip the `translation.override` when WAGTAIL_I18N_ENABLED is false; this accounts for the fact that existing sites may have used alternative / custom i18n implementations involving i18n_patterns, and on these sites we can't rely on the page's locale field to be meaningful. That way, we restore the pre-2.11 behaviour: if the existing i18n code was using some kind of wrapper around the get_url_parts call, then that will work again; and if not, the URL will reflect the current active locale, which is no worse than before.
Fixes#6518
If the models.py containing a custom user model directly or indirectly imports wagtail.admin.auth, this causes a circular dependency because wagtail.admin.auth attempts to import django.contrib.auth.views, which in turn depends on the custom user model. Fix this by moving the django.contrib.auth.views import inside reject_request.
* Catch PermissionDenied exceptions in require_admin_access decorator
* Fixed permissions errors for the documents views
* Added permissions tests for the images views
* Fixed some tests for limited permissions
* fixes#6352
Fixes#1158
Add config options WAGTAILDOCS_CONTENT_TYPES and WAGTAILDOCS_INLINE_CONTENT_TYPES to determine the Content-Type and Content-Disposition headers returned for documents when using the Django serve view, and default to application/pdf being served inline.
Add user_display_name template filter to simplify user display code
This replaces the `{{ some_rambling_expression_evaluating_to_a_user.get_full_name|default:some_rambling_expression_evaluating_to_a_user.get_username }}` pattern used all over the place.
Display user's full name (where available) in LogEntry listings
Don't use full name if it consists of whitespace (which happens on our test user models)
release note
- Add anyascii to replace unidecode
- Update wagtail.core.utils.string_to_ascii to use anyascii.
- Anyascii has a similar but not exactly the same encoding - see updates to tests.
Refs https://github.com/wagtail/wagtail/issues/3311
Fixes#6288
Many of the oembed endpoints currently listed with an http:// URL now redirect to https://. Changing these to https:// saves a redundant redirect and avoids failures where the http URL has been blocked (see #6288). Also simplified the patterns for matching http or https - the group in `http(?:s)?` is redundant and should just be `https?`.
* This commit only covers the migration of the icons in the menu and draftail editor. All
other admin menu icons remain implemented as before.
* Existing font based icon support still exists.
* Convert menu icons to SVG
* This could be considered a breaking change for any Wagtail sites or
packages that are leveraging Wagtail's Button and Icon React components.
* Remove references to unused `submenu-trigger` class
* Prefix icon `id`s with `icon-` to prevent `id` collisions
* Add hooks support (not yet documented) for adding custom icons
* Jest 24 is out but upgrading to it would require us to also update our Webpack tooling to Babel 7, which is quite significant work.
* Rewrite Draftail initialisation tests to stop relying on jsdom script parsing
When a slice is specifically set to [0:0], which would yield an empty list,
instead wagtail will clear the slice, effectively downloading the entire search
index.
This scenario happens when a search term does not return any results.
So every time you enter a search term that has no results, the entire search
index is downloaded, you don't really feel it because wagtail only downloads
the pk values, and it is unlikely a site has millions of pages, but it is still
very inefficient and unwanted.
* bulk_delete exists to avoid allowing users to delete a whole lot of pages all at once by mistake, when they think they're just deleting one. However, the move/delete analogue breaks down when you're talking about moving an entire subtree, because you're *not* directly altering the children of the moved Page.
* This method was inspired by a Lacey Williams Henschel (@williln) presentation at Wagtail Space US 2018, called 'What the Wagtail docs don't tell you'. https://www.youtube.com/watch?v=PCkxBNXWM64&t=1220s
* Add docs section reference/contrib/redirects
* Update ImageRendtion to use default_alt_text property of Image
* Update example in documentation
* Add a test for ImageRenditionField
* Resolves#5816
* Rewrite AbstractEmailForm render to use cleaned_data
* Add date time formatting to AbstractEmailForm's render method according to Django settings SHORT_DATE_FORMAT and
SHORT_DATETIME_FORMAT
* Previously it was iterating over `form` which left no place to remove
data from the submission without removing the field from the form (which
is inadvisable, as discussed on #4313)
* Preserve order of fields in form emails using cleaned data
* Add a test for consistent date rendering in email forms
* update form customisation examples and add note about date / time formatting in email form usage (docs)
* resolves#3733
* resolves#4313
* adds users view to group view (users filtered by that group)
* adds the ability to go to the users list for the group currently being edited (via header link)
* fix issue where the link to add a new user (when no users found) was broken
* resolves#5801
If validation rules prevent the multiple image upload view from
creating Image objects from just the image file, an UploadedImage object is
created instead, and turned into an image once the form is filled in.
* Fixes#847
* Add UploadedImage model and related views
* Update custom image model docs
According to the ARIA spec:
> A region that contains mostly site-oriented content, rather than page-specific content.
> Site-oriented content typically includes things such as the logo or identity of the site sponsor, and a site-specific search tool. A banner usually appears at the top of the page and typically spans the full width.
Where the `banner` role was applied was more page-specific than
site-specific. In addition, tags with `banner` roles should not live
under another landmark. To rectify, removed the misused banner roles.
Remove inappropriate contentinfo landmarks
According to ARIA spec 1.1
> A large perceivable region that contains information about the parent document.
> Examples of information included in this region of the page are copyrights and links to privacy statements.
They don't apply to the action buttons on where this was applied to.
Add main landmark to 404 page
- fixes#5099
- test_copy_page_with_excluded_parental_and_child_relations
- ensure the tests are wrapped in a try/finally so that the model is always reset back even if tests fail
- update page model tests
Fixeswagtail/wagtail#5937
This reverts Wagtail's behaviour to match Django's, where an error is
raised as a safety mechanism.
Projects relying on the non-safe behaviour should update e.g.
`MyModel.objects.delete()` to `MyModel.objects.all().delete()`.
Currently a select set of StreamField blocks like PageChooserBlock
expose a bulk_to_python method that is used to optimize their
retrieval from the database. As reported in issue 5926, ListBlock could
take advantage of this so that its child items are loaded at once,
instead of one at a time.
This change modifies how ListBlock.to_python works so that it calls its
child block's bulk_to_python, if defined. This allows for a single query
instead of one query per child item.
Note that this change doesn't add bulk_to_python to ListBlock itself,
meaning that individual ListBlocks in a StreamField or StructBlock are
still retrieved independently. But it does optimize the lookup for each
ListBlock.
Image operations sometimes calculate a target width or height of zero, which
make Willow raise a ValueError.
If an user uploads one such image it's possible to break the whole Wagtail
image manager/picker/uploader for all users.
The fix is to use a minimum of 1 pixel for either the target height or the
width. The image might lose some aspect ratio, but it's better than an
exception.
* Implement MultipleChoiceBlock (squashed commits from #5592)
* Omit widget from frozen kwargs
* Rename get_callable_choices to indicate it is an internal method
* Add release notes for MultipleChoiceBlock
Currently it is possible to pass the target attribute to a button
created using ModelAdmin's ButtonHelper framework. This allows you to
generate button links like <a ... target="_blank">.
For example, if adding a new button and modeling it after the existing
edit_button code [0], you can add {'target': "_blank"} to the returned
dict and it'll get passed to the template when the button is rendered.
To be consistent with PR 4844, and to be consistent with what seems to
be the best practice ([1], [2]), we should also support passing the rel
attribute, which would allow for creation of button links like <a ...
target="_blank" rel="noopener noreferrer">.
[0] 5e2f50403b/wagtail/contrib/modeladmin/helpers/button.py (L61-L73)
[1] https://developers.google.com/web/tools/lighthouse/audits/noopener
[2] https://www.jitbit.com/alexblog/256-targetblank---the-most-underestimated-vulnerability-ever/
The order of nested InlinePanels (recently formally added in 5566)
doesn't get saved properly due to some now-invalid assumptions in the JS
selector code.
Currently, Wagtail users can use the editor up/down arrows to order
InlinePanel elements that contain child InlinePanels, but these may not
be properly saved.
Before InlinePanel nesting was supported, it was a safer bet that a
child panel would only contain one hidden input named "-ORDER". With
nesting, however, a parent panel will also contain hidden inputs named
like this for its child panels. This breaks the logic used in the
ordering code.
This change modifies the logic to use the jQuery `.children()` selector
instead of `.next()`, ensuring that we reference the correct adjacent
panel item.
An easy way to test this against current master is to use the Wagtail
testapp test models that exercise this behavior:
1. `wagtail start testwagtail` to create a new project.
2. `cd testwagtail`
3. Edit testwagtail/settings/base.py to add the Wagtail test
application `'wagtail.tests.testapp'` to the list of `INSTALLED_APPS`.
For the admin to work properly with this app, you also need to add
`'wagtail.contrib.settings'` to that list and copy the definition of
`WAGTAILADMIN_RICH_TEXT_EDITORS` from wagtail/tests/settings.py.
4. `./manage.py migrate` to create your local database.
5. `./manage.py createsuperuser` to create an admin user.
6. Create a new Event Page
(http://localhost:8000/admin/pages/add/tests/eventpage/3/).
7. Fill in all required items, and then add multiple speakers under
"Speaker Lineup". For each speaker, add at least one Award. Save the
page.
8. Try using the up/down arrows to reorder the speakers (the parent
InlinePanel), and save the page.
9. Note that when the page reloads, the ordering hasn't been saved. If
you debug using the developer tools, you'll notice that this is because
the code being modified here selects the child panel items instead of
the adjacent parent panel item.
The `wagtail_urls` patterns is a catch-all list of urlpatterns, and will
prevent any patterns later in the list from being matched. The default
case when Django is in debug mode for local development is to use
`django-admin.py runserver`, and in this case the static patterns in the
example [are redundant][1]. However for anyone using a different server
for local development, this makes them work again.
[1]: https://docs.djangoproject.com/en/3.0/howto/static-files/#serving-static-files-during-development
Trying to compare revisions of a page that includes changes to a foreign key
field of a related model that declared a custom primary key failed with an
uncaught exception.
The root cause was ForeignObjectComparison filtering by the id field, which is
not present in models that declare a custom primary key.
The solution is simply to filter by pk instead of id, which always maps to the
primary key of the corresponding model.
Include a regression unit test.
- items longer then the page height are no longer broken by the submenu footer
- long lists of submenu items are no longer blocked by the footer (version number)
Other changes
- documents listing template - clean up white space
Documentation changes (editors manual)
- update images
- remove popular tags mention as this is no longer applicable
- add references to 'collection'
Resolves#2827
* note Python 3.8 support as provisional
* Remove mentions of minor doc fixes (there are many more fixes beyond the ones mentioned here, and including them all in the release notes would add too much noise...)
Fixes#5539. Transifex and Django's makemessages command have validation to catch invalid placeholder variables within translated strings - for example, where the translator has translated the variable name - but these only recognise old-style `%` formatting, not the `format` method, and so it's better for us to standardise on % formatting.
To reduce the burden on translators having to re-translate these strings, only the ones using named placeholders (`"Edited page {title}"`) rather than numeric ones (`"Edited page {0}"`) have been changed - hopefully the latter give less room for error.
Also fixed some incorrect use of plurals (verbose_name vs verbose_name_plural) in snippet confirmation messages.
- Typo in readme (verb did not agree with the subject)
- Grammatical error in topics/pages
- #5364 - Update URL config code block in getting-started/integrating-into-django
Work on compatibility is ongoing while Django 3.0 is still in development; we don't want this to be misinterpreted as a statement of formal Django 3.0 support (which we can't promise until the final release)
As per https://twitter.com/SaraSoueidan/status/1177622630763028480, certain browsers apply heuristics to decide whether `<table>` elements exist for layout or data purposes, and adjust the behaviour of their accessibility features accordingly. Given that TableBlock intentionally doesn't allow markup within cells, we can be reasonably sure that any tables created with it are genuine data tables, and should therefore indicate that using `role="table"`.
Fixes#5442. Building a User object for david@torchbox.com may cause problems if a custom user model is in use, and is redundant anyhow because there's no longer a registered gravatar for that email - we should just hard-code the default blank avatar instead.
The current block id generation only sets the id as the block is serialized for storage in the database, which means that the id is unavailable in the block until it is pulled back from the database. In my debugging this caused the id to be set to new values up to 3 times when saving a brand new page (each time with a new id).
This updated logic applies the new id to the actual block which makes it available right away and prevents the id from being regenerated.
This commit adds WAGTAIL_EMAIL_MANAGEMENT_ENABLED setting that defaults
to True, but when disabled, hides the 'Change email' button in account
management view, and disables the associated route. This is useful when
using external authentication method like LDAP or OpenID Connect where
email management is handled elsewhere.
Wagtail already includes WAGTAIL_PASSWORD_MANAGEMENT_ENABLED setting.
This is almost exact copy of that implementation.
50ms is the equivalent of about 200 words per minute, so typing slower than that
meant that the javascript would send an AJAX request between every single
keystroke. This change makes the javascript wait for 200ms between keystrokes,
which lets you finish typing the word you're looking for before it sends an AJAX
request.