Skip to content

Commit 8c574dc

Browse files
committed
Add ModelAdmin for Url and Link models
1 parent 8461710 commit 8c574dc

File tree

18 files changed

+1142
-161
lines changed

18 files changed

+1142
-161
lines changed

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
Unreleased
22

3+
* Migrate linkcheck views to `ModelAdmin` (Timo Brembeck, #186)
4+
* Add `ModelAdmin` for Url and Link models
35
* Move coverage view to management command (Timo Brembeck, #187)
46
* Add new management command `linkcheck_suggest_config`
57
* Delete coverage view

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ include README.rst
55
include linkcheck/locale/*/LC_MESSAGES/django.mo
66
exclude linkcheck/locale/*/LC_MESSAGES/django.po
77
recursive-include linkcheck/templates/linkcheck *
8+
recursive-include linkcheck/static/linkcheck *
89
recursive-include linkcheck/tests/media *

README.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ django-linkcheck
1313
A fairly flexible app that will analyze and report on links in any model that
1414
you register with it.
1515

16-
.. image:: https://github.com/DjangoAdminHackers/django-linkcheck/raw/master/linkcheck.jpg
16+
.. image:: examples/linkcheck.jpg
1717

1818
Links can be bare (urls or image and file fields) or
1919
embedded in HTML (linkcheck handles the parsing). It's fairly easy to override
@@ -50,11 +50,16 @@ Basic usage
5050

5151
#. Run ``./manage.py migrate``.
5252

53-
#. Add to your root url config::
53+
#. Register linkcheck models in your admin::
5454

55-
path('admin/linkcheck/', include('linkcheck.urls'))
55+
from django.contrib import admin
56+
from linkcheck.models import Link, Url
57+
from linkcheck.admin import LinkAdmin, UrlAdmin
5658

57-
#. View ``/admin/linkcheck/`` from your browser.
59+
admin.site.register(Url, UrlAdmin)
60+
admin.site.register(Link, LinkAdmin)
61+
62+
#. View ``/admin/linkcheck/url/`` from your browser.
5863

5964
We are aware that this documentation is on the brief side of things so any
6065
suggestions for elaboration or clarification would be gratefully accepted.

examples/linkcheck.jpg

664 KB
Loading

linkcheck.jpg

-69.5 KB
Binary file not shown.

linkcheck/admin/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from .link_admin import LinkAdmin
2+
from .url_admin import UrlAdmin
3+
4+
__all__ = [
5+
"LinkAdmin", "UrlAdmin"
6+
]

linkcheck/admin/link_admin.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
from django.contrib import admin, messages
2+
from django.template.defaultfilters import yesno
3+
from django.utils.translation import gettext_lazy as _
4+
5+
from ..models import Link, Url
6+
from ..templatetags.linkcheck_admin_tags import (
7+
linkcheck_actions,
8+
linkcheck_source,
9+
linkcheck_status_icon,
10+
linkcheck_url,
11+
)
12+
13+
14+
class LinkAdmin(admin.ModelAdmin):
15+
list_display = [
16+
'list_url',
17+
'list_status',
18+
'text',
19+
'list_content_object',
20+
'content_type',
21+
'list_field',
22+
'list_ignore',
23+
'list_actions',
24+
]
25+
actions = ['recheck', 'ignore', 'unignore']
26+
27+
@admin.display(ordering='url', description=Url._meta.get_field('url').verbose_name)
28+
def list_url(self, link):
29+
return linkcheck_url(link.url)
30+
31+
@admin.display(ordering='url__status', description=Url._meta.get_field('status').verbose_name)
32+
def list_status(self, link):
33+
return linkcheck_status_icon(link.url)
34+
35+
@admin.display(ordering='object_id', description=_('source'))
36+
def list_content_object(self, link):
37+
return linkcheck_source(link)
38+
39+
@admin.display(ordering='field', description=Link._meta.get_field('field').verbose_name)
40+
def list_field(self, link):
41+
return type(link.content_object)._meta.get_field(link.field).verbose_name
42+
43+
@admin.display(ordering='ignore', description=Link._meta.get_field('ignore').verbose_name)
44+
def list_ignore(self, link):
45+
return yesno(link.ignore)
46+
47+
@admin.display(description=_('Actions'))
48+
def list_actions(self, link):
49+
return linkcheck_actions(link.url, obj=link)
50+
51+
def has_add_permission(self, request, obj=None):
52+
return False
53+
54+
def has_change_permission(self, request, obj=None):
55+
return False
56+
57+
def has_delete_permission(self, request, obj=None):
58+
return False
59+
60+
@admin.action(description=_('Recheck selected links'))
61+
def recheck(self, request, queryset):
62+
for link in queryset:
63+
link.url.check_url(external_recheck_interval=0)
64+
if len(queryset) == 1:
65+
messages.success(
66+
request,
67+
_('The link "{}" was rechecked.').format(queryset[0].url),
68+
)
69+
else:
70+
messages.success(
71+
request,
72+
_('The selected links were rechecked.'),
73+
)
74+
75+
@admin.action(description=_('Ignore selected links'))
76+
def ignore(self, request, queryset):
77+
queryset.update(ignore=True)
78+
if len(queryset) == 1:
79+
messages.success(
80+
request,
81+
_('The link "{}" is now ignored.').format(queryset[0].url),
82+
)
83+
else:
84+
messages.success(
85+
request,
86+
_('The selected links are now ignored.'),
87+
)
88+
89+
@admin.action(description=_('No longer ignore selected links'))
90+
def unignore(self, request, queryset):
91+
queryset.update(ignore=False)
92+
if len(queryset) == 1:
93+
messages.success(
94+
request,
95+
_('The link "{}" is no longer ignored.').format(queryset[0].url),
96+
)
97+
else:
98+
messages.success(
99+
request,
100+
_('The selected links are no longer ignored.'),
101+
)
102+
103+
def changelist_view(self, request, extra_context=None):
104+
extra_context = extra_context or {}
105+
if request.GET.get('ignore__exact') == '1':
106+
title = _('Ignored links')
107+
elif request.GET.get('ignore__exact') == '0':
108+
title = _('Not ignored links')
109+
else:
110+
title = _('Links')
111+
extra_context['title'] = title
112+
return super().changelist_view(request, extra_context=extra_context)
113+
114+
class Media:
115+
css = {
116+
'all': ['linkcheck/css/style.css'],
117+
}
118+
js = ['linkcheck/js/actions.js']

0 commit comments

Comments
 (0)