Usage¶
For these examples we will use the following models:
class MyModel(models.Model):
age = models.IntegerField()
employed = models.NullBooleanField()#Yes,No,Unknown
degree = models.CharField(max_length = 2, choices = [["HS", "High School"],
["C", "College"],
["G", "Graduate"],
["PG", "Post Graduate"]]
)
class MyInstitution(models.Model):
name = models.CharField(max_length=50)
accredited = models.BooleanField()
def __str__(self):
return "%s" % self.name
To use django-modelqueryform in a project import it into forms.py:
import modelqueryform
Then we can use it as a Base class for your forms:
class MyModelQueryForm(modelqueryform.ModelQueryForm):
model = MyModel
inclue = ['age','employed','degree']
Thats it! Instantiating MyModelQueryForm gives us a form with 3 widgets
- Age (RangeField using a RangeWidget)
- Employed (MultipleChoiceField using a CheckboxSelectMultiple widget)
- Degree (MultipleChoiceField using a CheckboxSelectMultiple widget)
Once the form is POSTed to the view it is used to filter your model:
query_form = MyModelQueryForm(request.POST)
my_models = query_form.process()
process([data_set=None]) generates a Q object which is a logical AND of the Q objects generated for each widget. It uses the resulting Q object to filter the associated model class.
Note
process() optionally accepts a QuerySet of a model class ‘x’ where isinstance(x, ‘form model class’) is True If no QuerySet is passed, the Q object will run against model.objects.all()
Using pretty_print_query() you get a dict() of the form {str(field.label): str(field values)} to parse into a template:
query_form = MyModelQueryForm(request.POST)
query_parameters = query_form.pretty_print_query()
pretty_print_query() also accepts an argument fields_to_print, a list of names that must be a subset of self.changed_data.
Working with Relations¶
django-modelqueryform can work with realtionship fields in two different ways, either following the relation or using the relationship field as a choice field.
Let’s add a new field to MyModel from the example above:
class MyModel(models.Model):
...
institution = models.ForeignKey('MyInstitution')
If we want our users to be able to select for (non)-accredited institions we would instantiate the form like so:
class MyModelQueryForm(modelqueryform.ModelQueryForm):
model = MyModel
inclue = ['age','employed','degree', 'institution__accredited']
traverse_fields = ['institution',]
Alternatively we can use the relationship field as a MultipleChoiceField:
class MyModelQueryForm(modelqueryform.ModelQueryForm):
model = MyModel
inclue = ['age','employed','degree', 'institution']
Warning
To make the choices for a relationship field, django-modelqueryform does an objects.distinct() call. Be aware of the size of the resulting QuerySet
Defaults¶
djagno-modelqueryform tries to provide meaningful default where it can. Default widgets, Q objects, and print representation exist for model fields that are stored as numeric values or have choices (either defined or by default, ie. BooleanField(s))
Note
See Customization for how to handle field type that don’t have defaults
Default Fields
Model Field | Form Field/Widget | Q Object | Print Representation |
---|---|---|---|
AutoField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
BigIntegerField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
BinaryField | |||
BooleanField | MultipleChoiceField / CheckboxSelectMultiple | OR([field=value],…) | ‘CHOICE1,CHOICE2,…CHOICEn’ |
CharField | |||
CommaSeparatedIntegerField | |||
DateField | |||
DateTimeField | |||
DecimalField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
EmailField | |||
FileField | |||
FilePathField | |||
FloatField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
ImageField | |||
IntegerField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
IPAddressField | |||
GenericIPAddressField | |||
NullBooleanField | MultipleChoiceField / CheckboxSelectMultiple | OR([field=value],…) | ‘CHOICE1,CHOICE2,…CHOICEn’ |
PositiveIntegerField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
PositiveSmallIntegerField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
SlugField | |||
SmallIntegerField | RangeField / RangeWidget | AND([field__gte=min],[field__lte=max]), OR(field__isnull=True) | ‘MIN - MAX [(include empty values)]’ |
TextField | |||
TimeField | |||
URLField | |||
ForeignKey | MultipleChoiceField / CheckboxSelectMultiple | OR([field=value],…) | ‘CHOICE1,CHOICE2,…CHOICEn’ |
ManyToManyField | MultipleChoiceField / CheckboxSelectMultiple | OR([field=value],…) | ‘CHOICE1,CHOICE2,…CHOICEn’ |
OneToOneField | MultipleChoiceField / CheckboxSelectMultiple | OR([field=value],…) | ‘CHOICE1,CHOICE2,…CHOICEn’ |