diff --git a/README.rst b/README.rst index 3d4a855..0502160 100644 --- a/README.rst +++ b/README.rst @@ -83,6 +83,16 @@ customize the extracted links: ``image_fields``: a list of ``ImageField`` field names whose content will be considered as links. Empty ``ImageField`` content is always ignored. + ``filter_callable``: a callable which allows allows to pass a function as filter + for your linklist class. It allows to apply more advanced filter operations. + This function must be a class method and it should be passed the objects query + set and return the filtered objects. + Example usage in your linklists.py - only check latest versions: + @classmethod + def filter_callable(cls, objects): + latest = Model.objects.filter(id=OuterRef('id')).order_by('-version') + return objects.filter(version=Subquery(latest.values('version')[:1])) + Management commands ------------------- diff --git a/linkcheck/__init__.py b/linkcheck/__init__.py index 10b5672..d85f4f9 100644 --- a/linkcheck/__init__.py +++ b/linkcheck/__init__.py @@ -121,17 +121,6 @@ class Linklist: object_filter = None object_exclude = None - - # filter_callable allows to pass a function as filter for your linklist class. - # It allows to apply more advanced filter operations. - # This function must be a class method and it should be passed the objects query set - # and return the filtered objects. - # Example usage in your linklists.py - only check latest versions: - # @classmethod - # def filter_callable(cls, objects): - # latest = Model.objects.filter(id=OuterRef('id')).order_by('-version') - # return objects.filter(version=Subquery(latest.values('version')[:1])) - filter_callable = None def __get(self, name, obj, default=None): diff --git a/linkcheck/tests/sampleapp/linklists.py b/linkcheck/tests/sampleapp/linklists.py index 346bb65..f75effd 100644 --- a/linkcheck/tests/sampleapp/linklists.py +++ b/linkcheck/tests/sampleapp/linklists.py @@ -1,5 +1,6 @@ +from django.db.models import Subquery, OuterRef from linkcheck import Linklist -from linkcheck.tests.sampleapp.models import Author, Book +from linkcheck.tests.sampleapp.models import Author, Book, Journal class BookLinklist(Linklist): @@ -16,7 +17,18 @@ class AuthorLinklist(Linklist): url_fields = ['website'] +class JournalLinklist(Linklist): + """ Class to let linkcheck app discover fields containing links """ + model = Journal + html_fields = ['description'] + @classmethod + def filter_callable(cls, objects): + latest = Journal.objects.filter(title=OuterRef('title')).order_by('-version') + return objects.filter(version=Subquery(latest.values('version')[:1])) + + linklists = { 'Books': BookLinklist, 'Authors': AuthorLinklist, + 'Journals': JournalLinklist, } diff --git a/linkcheck/tests/sampleapp/models.py b/linkcheck/tests/sampleapp/models.py index c40034f..af87065 100644 --- a/linkcheck/tests/sampleapp/models.py +++ b/linkcheck/tests/sampleapp/models.py @@ -13,3 +13,9 @@ class Author(models.Model): # This model has purposefully no get_absolute_url name = models.CharField(max_length=50) website = models.URLField(blank=True) + + +class Journal(models.Model): + title = models.CharField(max_length=50) + description = models.TextField() + version = models.PositiveIntegerField(default=0) diff --git a/linkcheck/tests/test_linkcheck.py b/linkcheck/tests/test_linkcheck.py index 14784a3..aa4332b 100644 --- a/linkcheck/tests/test_linkcheck.py +++ b/linkcheck/tests/test_linkcheck.py @@ -21,7 +21,7 @@ from linkcheck.models import Link, Url from linkcheck.views import get_jquery_min_js -from .sampleapp.models import Author, Book +from .sampleapp.models import Author, Book, Journal #MOCK addinfurl @@ -425,3 +425,24 @@ class FixtureTestCase(TestCase): def test_fixture(self): self.assertEqual(Book.objects.count(), 1) + + +class FilterCallableTestCase(TestCase): + def test_filter_callable(self): + all_linklists = apps.get_app_config('linkcheck').all_linklists + all_linklists['Journals'].html_fields = [] + Journal.objects.create(title='My Title', description=""" + My description Example""") + Journal.objects.create(title='My Title', version=1, description=""" + My new description Example""") + all_linklists['Journals'].html_fields = ['description'] + # assert there are two versions of the same journal + self.assertEqual(Journal.objects.count(), 2) + # assert command just finds the latest version of same journals + out = StringIO() + call_command('findlinks', stdout=out) + self.assertEqual( + out.getvalue(), + "Finding all new links...\n" + "1 new Url object(s), 1 new Link object(s), 0 Url object(s) deleted\n" + )