django-classifier¶
Flexible constructor to create dynamic list of heterogeneous properties for some kind of entity. This set of helpers useful to create properties like contacts or attributes for describe car/computer/etc.
You must create your own models for each kind of entity but it gives more flexibility, more simpler and allow to easily change default behavior.
read Tutorial to see all picture of idea.
Content¶
Installation¶
Requirements¶
- Python 2.7, 3.4, 3.5
- Django 1.8, 1.9, 1.10
Official releases¶
Official releases are available from PyPI.
Download the .zip distribution file and unpack it. Inside is a script
named setup.py
. Enter this command:
python setup.py install
...and the package will install automatically.
or just install with help of pip:
pip install django-classifier
Development version¶
Alternatively, you can get the latest source from our git repository:
git clone http://github.com/django-stars/django-classifier.git django-classifier
Add django-classifier/classifier
folder to PYTHONPATH.
You can verify that the application is available on your PYTHONPATH by opening a Python interpreter and entering the following commands:
>> import classifier
>> classifier.VERSION
(0, 2)
Caution
The development version may contain bugs which are not present in the release version and introduce backwards-incompatible changes.
Tutorial¶
Configuration¶
Add classifier
to INSTALLED_APPS
in your setting.py
file:
INSTALLED_APPS = (
'djangp.contrib.auth',
# ...
'classifier',
)
Set up your models¶
You need to create two models for classifier structure and one for data.
First it’s basic model without extra data inherited from
ClassifierAbstract
:
from classifier.models import ClassifierAbstract
class ContactClassifier(ClassifierAbstract):
pass
Second model must contain ForeignKey
to model
that we created before and inherited from
ClassifierLabelAbstract
:
from classifier.models import ClassifierLabelAbstract
class ContactClassifierLabel(ClassifierLabelAbstract):
classifier = models.ForeignKey(ContactClassifier, related_name='labels')
Model for data pretty simple in general:
ForeignKey
to label model
(ContactClassifierLabel
in tutorial) and
CharField
for value:
from django.conf import settings
from django.db import models
class Contact(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='contacts'
)
kind = models.ForeignKey(ContactClassifier)
value = models.CharField(max_length=500)
Then make and run migrations and you are ready to use django-classifier
:
python manage.py makemigrations
python manage.py migrate
Add some data to classifier models¶
Lets add some data to ContactClassifier
and ContactClassifierLabel
:
contact_classifier1 = ContactClassifier.objects.create(
kind='phone',
value_type=ContactClassifier.TYPES.STRING,
value_validator=r'^\+\d{12}$',
only_one_required=False,
)
contact_classifier1.labels.create(label='Mobile')
contact_classifier1.labels.create(label='Work')
contact_classifier1.labels.create(label='Home')
contact_classifier2 = ContactClassifier.objects.create(
kind='im',
value_type=ContactClassifier.TYPES.STRING,
value_validator=None,
only_one_required=False,
)
contact_classifier2.labels.create(label='Skype')
contact_classifier2.labels.create(label='Jabber')
Create form for validation¶
To validate values based on classifier record, for this django-classifier
has ClassifierFormMixin
:
from django import forms
from classifier.forms import ClassifierFormMixin
from .models import Contact
class ContactForm(ClassifierFormMixin, forms.ModelForm):
CLASSIFIER_VALUE_FIELD = 'value'
class Meta:
model = Contact
fields = ('user', 'kind', 'value', )
You have to specify
CLASSIFIER_VALUE_FIELD
attribute to identify name of value field to attach validation based on
classifier record.
Playing with formset¶
classifier
provide own FormSet
class
ClassifierFormSet
that will add extra forms
for mandatory records and validate if all of them are filled in:
from django.contrib.auth import get_user_model
from django.forms import modelformset_factory
from classifier.formsets import ClassifierFormSet
from .forms import UserForm, ContactForm
from .models import Contact
ContactFormSet = modelformset_factory(
Contact,
formset=ClassifierFormSet,
form=ContactForm
)
user = get_user_model().objects.create('login', 'password')
contact_formset = ContactFormSet(queryset=user.contacts.all())
print(len(contact_formset.forms))
print(contact_formset.forms[0].initial)
For now any of classifier records are not marked as required and formset has only one blank forms as default in Django.
But if you will mark both classifiers as
only_one_required
you will have
two forms with prepopulated labels (first available label):
ContactClassifier.objects.all().update(only_one_required=True)
contact_formset = ContactFormSet(queryset=user.contacts.all())
print(len(contact_formset.forms))
print(contact_formset.forms[0].initial)
print(contact_formset.forms[1].initial)
If you will mark all labels as
required
then you will
have 5 forms by default and all of them will be required:
ContactClassifier.objects.all().update(only_one_required=False)
ContactClassifierLabel.objects.all().update(required=True)
contact_formset = ContactFormSet(queryset=user.contacts.all())
print(len(contact_formset.forms))
classifier
package¶
classifier.models
¶
ClassifierAbstract
¶
-
class
classifier.models.
ClassifierAbstract
(*args, **kwargs)[source]¶ Base class to create classifier models. Will provide base data and functions like validation and
to_python
(convert from string to real type).In simplest case should be created model just inherited from this abstract model without extra code.
kind
- custom identificator for classifier type (like: phone)value_type
- expected type of value (like: string)value_validator
- regex to validate extered value (like: +d{12})only_one_required
- checkmark to make one on available lables requiredSupported types:
int
,float
,string
,boolean
,date
,datatime
.Labels with kind give posibility to create one type of record with different names, like kind is phone and available lables are “Mobile”, “Home”, “Work” etc.
-
kind
¶ custom identificator for classifier type (like: phone)
-
value_type
¶ expected type of value (like: string)
-
value_validator
¶ regex to validate extered value (like: +d{12})
-
only_one_required
¶ checkmark to make one on available lables required
-
ClassifierLabelAbstract
¶
-
class
classifier.models.
ClassifierLabelAbstract
(*args, **kwargs)[source]¶ Base model class to define several human readable names for each classifier kind.
-
label
¶ human redable label for data
-
required
¶ checkmark to make label required
Returns: field related to model inherited from ClassifierAbstract. Raises: ClassifierModelNotFound – if related field wasn’t found Caution
not field name
-
classifier.formsets
¶
ClassifierFormSet
¶
-
class
classifier.formsets.
ClassifierFormSet
(*args, **kwargs)[source]¶ -
add_required_to_extra
()[source]¶ Method create extra forms for required records from classifier with selected needed kinds by default.
-
classifier_label_model
¶ Property return model inherited from
ClassifierLabelAbstract
and used for one of field in model for this formset.Returns: model inherited from ClassifierLabelAbstract
Raises: ClassifierLabelModelNotFound – field can not be found
Return name of field related to model inherited from
ClassifierLabelAbstract
.
-
validate_required
()[source]¶ Validate if all required records are filled in
Raises: django.core.exceptions.ValidationError – if one or mode records are absent
-
classifier.forms
¶
ClassifierFormMixin
¶
-
class
classifier.forms.
ClassifierFormMixin
(*args, **kwargs)[source]¶ Formset form mixin to enable validation for value connected to classifier.
-
CLASSIFIER_VALUE_FIELD
= None¶ Name of field for value used in relation with classifier
-
classifier_label_fieldname
¶ Returns: Return name of field that is relation to end model inherited from ClassifierLabelAbstract
Raises: ClassifierLabelModelNotFound – if field can not be found
-
classifier_label_model
¶ Returns: end model inherited from ClassifierLabelAbstract
used in current formRaises: ClassifierLabelModelNotFound – if related field wasn’t found
-
setup_value_validators
()[source]¶ Attach validator for value field specified in
CLASSIFIER_VALUE_FIELD
Raises: NoValueFieldNameSpecified – if CLASSIFIER_VALUE_FIELD
is blank
-
validate_value_field
()[source]¶ Validate value based on classifier record.
Will be attathed to right field by call
setup_value_validators()
in__init__()
-