This is a newforms field for XFN relationships.
It normalizes input by removing excess whitespace, converting to lowercase and removing duplicates.
This field also validates the relationship according to the XFN profile: me
can only appear by itself and, at most, one value from each of the family, friendship and geographical categories is allowed.
The XFN_*
constants would probably be imported from somewhere else in practice, but are included here for simplicity.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | from django import newforms as forms
XFN_FAMILY_RELS = ('child', 'kin', 'parent', 'sibling', 'spouse')
XFN_FRIENDSHIP_RELS = ('acquaintance', 'contact', 'friend')
XFN_GEOGRAPHICAL_RELS = ('co-resident', 'neighbor')
XFN_IDENTITY_RELS = ('me',)
XFN_PHYSICAL_RELS = ('met',)
XFN_PROFESSIONAL_RELS = ('colleague', 'co-worker')
XFN_ROMANTIC_RELS = ('crush', 'date', 'muse', 'sweetheart')
XFN_RELS = (
XFN_FAMILY_RELS + XFN_FRIENDSHIP_RELS + XFN_GEOGRAPHICAL_RELS
+ XFN_IDENTITY_RELS + XFN_PHYSICAL_RELS + XFN_PROFESSIONAL_RELS
+ XFN_ROMANTIC_RELS
)
xfn_family_rels = set(XFN_FAMILY_RELS)
xfn_friendship_rels = set(XFN_FRIENDSHIP_RELS)
xfn_geographical_rels = set(XFN_GEOGRAPHICAL_RELS)
xfn_rels = set(XFN_RELS)
class XFNField(forms.Field):
"""Field to normalize and validate an XFN relationship.
Strips extra whitespace, converts to lowercase and removes duplicates.
Enforces exclusivity for the ``me`` value and allows at most one value from
each of the family, friendship and geographical categories.
Sorts values alphabetically -- not required, but *feels* right.
http://gmpg.org/xfn/11
"""
default_error_messages = {
'family': u'XFN allows only one family value.',
'friendship': u'XFN allows only one friendship value.',
'invalid': u'Enter a valid XFN relationship.',
'geographical': u'XFN allows only one geographical value.',
'me': u'The "me" relationship can\'t be used with other values.',
'required': u'Enter an XFN relationship.'
}
def clean(self, value):
value = super(XFNField, self).clean(value)
if value in forms.fields.EMPTY_VALUES:
return u''
rels = set(value.strip().lower().split())
if len(rels - xfn_rels):
raise forms.ValidationError(self.error_messages['invalid'])
if len(rels & xfn_family_rels) > 1:
raise forms.ValidationError(self.error_messages['family'])
if len(rels & xfn_friendship_rels) > 1:
raise forms.ValidationError(self.error_messages['friendship'])
if len(rels & xfn_geographical_rels) > 1:
raise forms.ValidationError(self.error_messages['geographical'])
if 'me' in rels and len(rels) > 1:
raise forms.ValidationError(self.error_messages['me'])
return u' '.join(sorted(rels))
def widget_attrs(self, widget):
return {'class': 'xfn'}
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 4 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Please login first before commenting.