Skip to content

Instantly share code, notes, and snippets.

@mcroydon
Created February 3, 2010 05:09
Show Gist options
  • Save mcroydon/293343 to your computer and use it in GitHub Desktop.
Save mcroydon/293343 to your computer and use it in GitHub Desktop.
from django import forms
from django.utils.encoding import force_unicode
from taggit.managers import TaggableManager
from taggit.utils import parse_tags
# Extended from django-taggit (http://github.com/alex/django-taggit)
class ExtendedTagField(forms.CharField):
"""An extended TagField that makes use of the tag parser from django-tagging."""
def clean(self, value):
return parse_tag_input(value)
class ExtendedTaggableManager(TaggableManager):
"""An extended TaggableManager that makes use of the tag parser from django-tagging."""
def __init__(self, *args, **kwargs):
super(ExtendedTaggableManager, self).__init__(*args, **kwargs)
def formfield(self, form_class=ExtendedTagField, **kwargs):
defaults = {
"label": "Tags",
"help_text": "A list of tags separated either by commas or spaces. Use quotes for multi-word tags."
}
defaults.update(kwargs)
return form_class(**kwargs)
# From django-tagging (http://code.google.com/p/django-tagging/)
def parse_tag_input(input):
"""
Parses tag input, with multiple word input being activated and
delineated by commas and double quotes. Quotes take precedence, so
they may contain commas.
Returns a sorted list of unique tag names.
"""
if not input:
return []
input = force_unicode(input)
# Special case - if there are no commas or double quotes in the
# input, we don't *do* a recall... I mean, we know we only need to
# split on spaces.
if u',' not in input and u'"' not in input:
words = list(set(split_strip(input, u' ')))
words.sort()
return words
words = []
buffer = []
# Defer splitting of non-quoted sections until we know if there are
# any unquoted commas.
to_be_split = []
saw_loose_comma = False
open_quote = False
i = iter(input)
try:
while 1:
c = i.next()
if c == u'"':
if buffer:
to_be_split.append(u''.join(buffer))
buffer = []
# Find the matching quote
open_quote = True
c = i.next()
while c != u'"':
buffer.append(c)
c = i.next()
if buffer:
word = u''.join(buffer).strip()
if word:
words.append(word)
buffer = []
open_quote = False
else:
if not saw_loose_comma and c == u',':
saw_loose_comma = True
buffer.append(c)
except StopIteration:
# If we were parsing an open quote which was never closed treat
# the buffer as unquoted.
if buffer:
if open_quote and u',' in buffer:
saw_loose_comma = True
to_be_split.append(u''.join(buffer))
if to_be_split:
if saw_loose_comma:
delimiter = u','
else:
delimiter = u' '
for chunk in to_be_split:
words.extend(split_strip(chunk, delimiter))
words = list(set(words))
words.sort()
return words
def split_strip(input, delimiter=u','):
"""
Splits ``input`` on ``delimiter``, stripping each resulting string
and returning a list of non-empty strings.
"""
if not input:
return []
words = [w.strip() for w in input.split(delimiter)]
return [w for w in words if w]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment