django-taggit

django-taggit doesn't support smart quotes


When submitting a form with a Django-taggit tag field, tags containing multiple words are kept together/not broken by the space by wrapping the tag in quotes, ex "foo bar" should create tags of ["foo bar"]. But, on devices that support smart quotes, taggit won't identify the smart quotes and will break apart the submission as [bar", "foo].

The issue lies in _parse_tags in utils which only checks '"' (unicode 34). Whereas on my iPhone, smart quotes by default are unicode 8220-1. Of course, the user can disable smart punctuation by going to settings > general > keyboard and toggle-off smart punctuation which will fix the issue. But, asking user's to accommodate the issue doesn't really seem like a solution.

The smart punctuation can't be dealt with in clean_tags either since _parse_tags is called upstream after the field has been cleaned.


Solution

  • I dealt with this by updating the form data before field clean is called and mapped any smart quotes to normal unicode 34 quotes.

    from collections import OrderedDict.
    
    class TaggitForm(forms.Form):
    # the basic ascii quote in unicode is 34, ex: '"'
    _quote_map = OrderedDict({
        # in unicode since it would be hard to tell what characters are being used visually
        # old: new
    
        # apple (at least iPhone) smart quotes
        8220: 34,
        8221: 34,
        8222: 34,
    })
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    
        # get a mutable copy of QueryDict
        self.data = self.data.copy()
    
        if 'tags' in self.data:
            tags = self.data['tags']
            for k, v in self._quote_map.items():
                tags = tags.replace(chr(k), chr(v))
    
            self.data['tags'] = tags
    

    This so far has seemed to fix the issue.