Created
February 3, 2010 05:09
-
-
Save mcroydon/293343 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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