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] = None
WEBMENTIONS_DOMAINS_INCOMING_DENY: Iterable[str] = None
WEBMENTIONS_DOMAINS_OUTGOING_ALLOW: Iterable[str] = None
WEBMENTIONS_DOMAINS_OUTGOING_DENY: Iterable[str] = None
WEBMENTIONS_DOMAINS_OUTGOING_TAG_ALLOW: str = None
WEBMENTIONS_DOMAINS_OUTGOING_TAG_DENY: str = None
quote
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 link
s 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-of
u-like-of
u-listen-of
u-in-reply-to
u-repost-of
u-translation-of
u-watch-of
The /webmention/get
endpoint serializes these values in the type
field respectively as:
bookmark
like
listen
reply
repost
translation
watch
type
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>
...
Incoming webmentions may now target any path, not just those that map directly to a mentionable model.