django-wm
Automatic Webmention functionality for Django models.
Automatic Webmention functionality for Django models.
wagtail>=6.2.
wagtail==6.2, the implementation of RoutablePageMixin.route was changed to add the routable_resolver_match attribute to the given request object. get_model_for_url_by_wagtail previously called that method with request=None (because there is no relevant request object available at the time webmentions are processed), so trying to set that attribute on the request fails.get_model_for_url_by_wagtail now creates and passes a dummy instance of HttpRequest when calling that method.Warning
python manage.py migrate required for new fields.
Added Webmention.has_been_read: bool field.
mentions.context_processors.unread_webmentions adds unread_webmentions field to template context, containing the queryset of unread Webmention objects.New objects manager for Webmention with some common filters and actions.
WEBMENTIONS_DOMAINS_INCOMING_ALLOW: Iterable[str] = NoneWEBMENTIONS_DOMAINS_INCOMING_DENY: Iterable[str] = NoneWEBMENTIONS_DOMAINS_OUTGOING_ALLOW: Iterable[str] = NoneWEBMENTIONS_DOMAINS_OUTGOING_DENY: Iterable[str] = NoneWEBMENTIONS_DOMAINS_OUTGOING_TAG_ALLOW: str = NoneWEBMENTIONS_DOMAINS_OUTGOING_TAG_DENY: str = Nonequote field now uses a textarea widget for comfier editing.Added management command mentions_reverify [filters ...] [--all]
field=value queryset filters, or --all to reprocess all of them.Added management command mentions_pending to replace pending_mentions for naming consistency with other commands.
pending_mentions still works though.Now compatible with Wagtail>=3.0.3 (previously >=4.0).
mentions_wagtail_path still requires >=4.0: use mentions_wagtail_route or mentions_wagtail_re_path.Warning
This update alters fields on MentionableMixin so you will need to run makemigrations and migrate after upgrading!
MentionableMixin:
allow_outgoing_webmentions default now configurable via settings.WEBMENTIONS_ALLOW_OUTGOING_DEFAULT.Removed slug field. If you use this field you can restore the previous behaviour by adding the following to your model.
class MyModel(MentionableMixin, models.Model):
slug = models.SlugField(unique=True)
@classmethod
def resolve_from_url_kwargs(cls, slug, **url_kwargs):
return cls.objects.get(slug=slug)
Deprecated methodall_text, replaced by get_content_html. Overriding all_text still works for now but will log a warning asking you to rename the method.
Moved template files to mentions sub-directory. If you have custom overrides of these templates in your root templates/ directory please move them to templates/mentions/.
Added user agent header to all network requests.
settings.WEBMENTIONS_USER_AGENT: str.Admin-facing strings are now translatable.
Added urlpatterns helper functions mentions_path, mentions_re_path for (hopefully) simpler setup.
resolve_from_url_kwargs on your MentionableMixin implementation.Support for Wagtail.
Page models should implement MentionableMixin as usual.RoutablePageMixin should use the new @mentions_wagtail_path, @mentions_wagtail_re_path decorators in place of the Wagtail equivalents @path, @re_path.
mentions_path and mentions_re_path.If using RichTextField call richtext on any RichTextField values in get_content_html:
from wagtail.templatetags.wagtailcore_tags import richtext
class MyModel(MentionableMixin, Page):
...
def get_content_html(self) -> str:
return f"{richtext(self.overview)} {richtext(self.body)}"
Wiki pages are now live! These will be kept up-to-date going forwards but may not be useful for pre-4.0 versions.
Fix: Relative URLs in h-card homepage or avatar are now resolved to absolute URLs.
Resolves #38: Revalidate target URLs when handling pending mentions
Resolves #41: Find correct endpoint when multiple links in HTTP header.
Added settings.WEBMENTIONS_INCOMING_TARGET_MODEL_REQUIRED [bool | default=False]. If True, incoming mentions are only accepted if their target resolves to a MentionableMixin instance.
Added settings.WEBMENTIONS_ALLOW_SELF_MENTIONS [bool | default=True].
False, outgoing links that target your own domain (as specified by settings.DOMAIN_NAME) will be ignored - you will only submit mentions to other domains.True, outgoing links that use a relative path (e.g. href="/article/1/") are now supported.Fix: WebmentionHeadMiddleware no longer overwrites existing links in HTTP header when adding webmention endpoint.
Fix: Webmention ’notes’ no longer persists across instances.
If upgrading from an older version please be aware of these changes:
MentionableMixin.allow_incoming_webmentions field has been removed.PendingIncomingWebmention and PendingOutgoingContent will be deleted.
Thanks to @philgyford for reporting most of the issues referenced here.
Resolves #25.
Added QuotableMixin.post_type field.
Incoming webmentions are now checked for the following microformat properties that describe the type of mention they are:
u-bookmark-ofu-like-ofu-listen-ofu-in-reply-tou-repost-ofu-translation-ofu-watch-ofThe /webmention/get endpoint serializes these values in the type
field respectively as:
bookmarklikelistenreplyreposttranslationwatchtype is specified this defaults to webmention.Resolves #30
MentionableMixin.should_process_webmentions() -> bool method to enable custom logic.Resolves #31
Resolves #32
#anchor links no longer treated as webmention targets.h-card.
h-card that is directly related to the mention link (embedded in p-author of a parent h-entry or h-feed container).h-card on the page.HCard.from_soup() classmethod. Parsing logic moved to tasks.incoming.parsing package.Resolves #36
PendingIncomingWebmention and PendingOutgoingContent to avoid duplication.
django-wm this will delete any existing Pending... model instances.PendingIncomingWebmention and OutgoingWebmentionStatus now implement the new RetryableMixin.WEBMENTIONS_MAX_RETRIES, WEBMENTIONS_RETRY_INTERVAL, WEBMENTIONS_TIMEOUT below for customisation details.New dashboard/ view: a simple overview of recent mentions.
Webmention, OutgoingWebmentionStatus, PendingIncomingWebmention, PendingOutgoingContent and info on their current status.mentions.view_webmention_dashboard permission.settings.WEBMENTIONS_DASHBOARD_PUBLIC = True.New optional settings:
settings.WEBMENTIONS_TIMEOUT [float | default=10] specifies the time (in seconds) to wait for network calls to resolve.settings.WEBMENTIONS_RETRY_INTERVAL [int | default=600] specifies the minimum time (in seconds) to wait before retrying to process a webmention.settings.WEBMENTIONS_MAX_RETRIES [int | default=5] specifies how many times we can attempt to process a mention before giving up.settings.WEBMENTIONS_DASHBOARD_PUBLIC [bool | default=False] specifies whether the the dashboard/ view can be viewed by anyone. If False (default), the dashboard/ view is only available to users with mentions.view_webmention_dashboard permission.WebmentionHeadMiddleware
request.META.SERVER_PORT may not be reliable depending on reverse proxy configuration.MentionableMixin:
mentions() is now a method, not a property.allow_incoming_webmentions as it has never been used for anything.Streamlined template tags
{% load webmentions_endpoint %} replaced by {% load webmentions %}.{% webmention_endpoint %} replaced by {% webmentions_endpoint %} (used in HTML <head>).{% webmentions_dashboard %} creates a <a>link</a> to your webmentions/dashboard/ view.Resolves #28
New MentionableMixin classmethod: resolve_from_url_kwargs(**url_kwargs)
urlpatterns path.<slug:slug> to look up your object by a unique
slug field.e.g.
# urls.py
urlpatterns = [
path(
fr"<int:year>/<int:month>/<int:day>/<slug:post_slug>/",
MyBlogPostView.as_view(),
name="my-blog",
kwargs={
"model_name": "myapp.MyBlog",
},
),
]
# models.py
class MyBlog(MentionableMixin, models.Model):
date = models.DateTimeField(default=timezone.now)
slug = models.SlugField()
content = models.TextField()
def all_text(self):
return self.content
def get_absolute_url(self):
return reverse(
"my-blog",
kwargs={
"year": self.date.strftime("%Y"),
"month": self.date.strftime("%m"),
"day": self.date.strftime("%d"),
"post_slug": self.slug,
}
)
@classmethod
def resolve_from_url_kwargs(cls, year, month, day, post_slug, **url_kwargs):
return cls.objects.get(
date__year=year,
date__month=month,
date__day=day,
slug=post_slug,
)
mentions.resolution.get_model_for_url_path now delegates to
MentionableMixin.resolve_from_url_kwargs to resolve captured URL parameters to a model instance.Merges #24: QuotableMixin.published can now be overriden - thanks @garrettc.
Fixes #26: requests 2.20 or greater (until version 3) are now allowed. Likewise for beautifulsoup4 4.6 and mf2py 1.1.
Added get_mentions_for_view(HttpRequest) -> Iterable[QuotableMixin] convenience method. This may be used to retrieve mentions for rendering directly in a Django template, as an alternative to using the webmention/get endpoint from a frontend script.
Added setting WEBMENTIONS_USE_CELERY (boolean, default True)
False:
celery does not need to be installedPendingIncomingWebmention and PendingOutgoingContent are created to store the required
data for later batch-processing.manage.py pending_mentions can be used to process these data./get endpoint:
type with value webmention or simple so they can be differentiated when displaying.Updated instructions for installation with or without celery.
Migrations are now included. If you are upgrading from any 1.x.x version please follow these instructions to avoid data loss. Thanks to @GriceTurrble for providing these instructions.
requirements.txt celery version updated to 5.2.2 due to CVE-2021-23727. If you are upgrading from 4.x please follow the upgrade instructions provided by Celery.
/get endpoint:
status from JSON object - now uses HTTP response codes 200 if the target url was resolved correctly or 404 otherwise.// https://example.org/webmention/get?url=my-article
// Old 1.x.x response
{
"status": 1,
"target_url": "https://example.org/my-article",
"mentions": [
{
"hcard": {},
"quote": null,
"source_url": "https://another-example.org/their-article",
"published": "2020-01-17T21:45:24.542Z"
}
]
}
// https://example.org/webmention/get?url=my-article
// New 2.0.0 response with HTTP status 200 (or 404 if target_url does not exist)
{
"target_url": "https://example.org/my-article",
"mentions": [
{
"hcard": null,
"quote": null,
"source_url": "https://another-example.org/their-article",
"published": "2020-01-17T21:45:24.542Z"
}
]
}
Use{% webmention_endpoint %} template tag to include your Webmentions endpoint in your Django template to help other sites find it easily.
{% load webmention_endpoint %}
<!-- my-template.html -->
...
<head>
<!-- Rendered as <link rel="webmention" href="/webmention/" /> -->
{% webmention_endpoint %}
</head>
...