Commit 8e7d741a by Frank Wiles

Removing taggit.contrib.suggest to separate taggit_suggest project

parent 288b794b
include taggit/contrib/suggest/README.txt
recursive-include docs *.txt recursive-include docs *.txt
recursive-include taggit/locale * recursive-include taggit/locale *
...@@ -11,7 +11,6 @@ if not settings.configured: ...@@ -11,7 +11,6 @@ if not settings.configured:
INSTALLED_APPS=[ INSTALLED_APPS=[
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'taggit', 'taggit',
'taggit.contrib.suggest',
'taggit.tests', 'taggit.tests',
] ]
) )
...@@ -21,7 +20,7 @@ from django.test.simple import run_tests ...@@ -21,7 +20,7 @@ from django.test.simple import run_tests
def runtests(*test_args): def runtests(*test_args):
if not test_args: if not test_args:
test_args = ['tests', 'suggest'] test_args = ['tests']
parent = dirname(abspath(__file__)) parent = dirname(abspath(__file__))
sys.path.insert(0, parent) sys.path.insert(0, parent)
failures = run_tests(test_args, verbosity=1, interactive=True) failures = run_tests(test_args, verbosity=1, interactive=True)
......
...@@ -21,7 +21,6 @@ setup( ...@@ -21,7 +21,6 @@ setup(
package_data = { package_data = {
'taggit': [ 'taggit': [
'locale/*/LC_MESSAGES/*', 'locale/*/LC_MESSAGES/*',
'contrib/suggest/README.txt',
], ],
}, },
classifiers=[ classifiers=[
......
taggit.contrib.suggest
======================
This add on module allows you to easily associate keywords and regular
expressions with a Tag object. This is useful to help keep your database
getting filled up with several similar tags that really represent the same
thing.
For example, if your site is a humor site you might want to collapse all of
#fun, #funny, #funnies, #hilarious, #rofl, and #lol into one tag #funny. The
``suggest_tags()`` function in ``taggit.contrib.suggest.utils`` will give you a
list of tags that seem appropriate for the text content given to it.
Unlike the rest of ``django-taggit``, ``suggest`` requires Django 1.2.
Usage
=====
Put ``'taggit.contrib.suggest'`` into ``INSTALLED_APPS`` and run a syncdb to
create the necessary models. This will add ``Keywords`` and
``Regular Expression`` inlines to the default ``django-taggit`` admin. Once
you've populated those based on your site you can do a simple:
.. sourcecode:: python
from taggit.contrib.suggest.utils import suggest_tags
tags = suggest_tags(content='Some textual content...')
TODO
====
* In a later version I hope to a simple way to help determine keywords for you
automatically, by learning from your past tags and content.
from django.contrib import admin
from taggit.admin import TaggedItemInline
from taggit.contrib.suggest.models import TagKeyword, TagRegex
from taggit.models import Tag
class TagKeywordInline(admin.StackedInline):
model = TagKeyword
class TagRegxInline(admin.StackedInline):
model = TagRegex
class TagSuggestAdmin(admin.ModelAdmin):
inlines = [
TaggedItemInline,
TagKeywordInline,
TagRegxInline,
]
admin.site.unregister(Tag)
admin.site.register(Tag, TagSuggestAdmin)
import re
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
from taggit.models import Tag
try:
import Stemmer
except ImportError:
Stemmer = None
class TagKeyword(models.Model):
"""
Model to associate simple keywords to a Tag
"""
tag = models.ForeignKey(Tag, related_name='keywords')
keyword = models.CharField(max_length=30)
stem = models.CharField(max_length=30)
def __unicode__(self):
return "Keyword '%s' for Tag '%s'" % (self.keyword, self.tag.name)
def save(self, *args, **kwargs):
"""
Stem the keyword on save if they have PyStemmer
"""
language = kwargs.pop('stemmer-language', 'english')
if not self.pk and not self.stem and Stemmer:
stemmer = Stemmer.Stemmer(language)
self.stem = stemmer.stemWord(self.keyword)
super(TagKeyword, self).save(*args, **kwargs)
def validate_regex(value):
"""
Make sure we have a valid regular expression
"""
try:
re.compile(value)
except Exception:
# TODO: more restrictive in the exceptions
raise ValidationError('Please enter a valid regular expression')
class TagRegex(models.Model):
"""
Model to associate regular expressions with a Tag
"""
tag = models.ForeignKey(Tag, related_name='regexes')
name = models.CharField(max_length=30)
regex = models.CharField(
max_length=250,
validators=[validate_regex],
help_text=_('Enter a valid Regular Expression. To make it '
'case-insensitive include "(?i)" in your expression.')
)
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
"""
Make sure to validate
"""
self.full_clean()
super(TagRegex, self).save(*args, **kwargs)
from django.core.exceptions import ValidationError
from django.test import TestCase
from taggit.contrib.suggest.models import TagKeyword, TagRegex
from taggit.contrib.suggest.utils import suggest_tags
from taggit.models import Tag
class SuggestCase(TestCase):
def test_simple_suggest(self):
ku_tag = Tag.objects.create(name='ku')
TagKeyword.objects.create(
tag=ku_tag,
keyword='kansas university'
)
suggested_tags = suggest_tags('I used to be a student at kansas university')
self.assertTrue(ku_tag in suggested_tags)
def test_regex_suggest(self):
ku_tag = Tag.objects.create(name='ku')
TagRegex.objects.create(
tag=ku_tag,
name='Find University of Kansas',
regex='University\s+of\s+Kansas'
)
suggested_tags = suggest_tags('I was once a student at the University of Kansas')
self.assertTrue(ku_tag in suggested_tags)
def test_bad_regex(self):
ku_tag = Tag.objects.create(name='ku')
TagKeyword.objects.create(
tag=ku_tag,
keyword='kansas university'
)
new_regex = TagRegex(
tag=ku_tag,
name='Find University of Kansas',
regex='University\s+of(\s+Kansas'
)
self.assertRaises(ValidationError, new_regex.save)
suggested_tags = suggest_tags('I was once a student at the University '
'of Kansas. Also known as kansas university by the way.')
self.assertTrue(ku_tag in suggested_tags)
import re
from taggit.contrib.suggest.models import TagKeyword, TagRegex
from taggit.models import Tag
def _suggest_keywords(content):
"""
Suggest by keywords
"""
suggested_keywords = set()
keywords = TagKeyword.objects.all()
for k in keywords:
# Use the stem if available, otherwise use the whole keyword
if k.stem:
if k.stem in content:
suggested_keywords.add(k.tag_id)
elif k.keyword in content:
suggested_keywords.add(k.tag_id)
return suggested_keywords
def _suggest_regexes(content):
"""
Suggest by regular expressions
"""
# Grab all regular expressions and compile them
suggested_regexes = set()
regex_keywords = TagRegex.objects.all()
# Look for our regular expressions in the content
for r in regex_keywords:
if re.search(r.regex, content):
suggested_regexes.add(r.tag_id)
return suggested_regexes
def suggest_tags(content):
"""
Suggest tags based on text content
"""
suggested_keywords = _suggest_keywords(content)
suggested_regexes = _suggest_regexes(content)
suggested_tag_ids = suggested_keywords | suggested_regexes
return Tag.objects.filter(id__in=suggested_tag_ids)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment