Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ master (unreleased)

* Added a make target to install the demo site.
* Added django-perf-rec module for tests and improved SQL queries in `ContextFormDetailView` (#54, #154, #160).
* Added test to count queries on dynamic form queryset + improve performances (#155, #156, #162).


Release 0.5.0 (2017-01-10)
Expand Down
14 changes: 14 additions & 0 deletions demo/tests/perfs/test_forms.perf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
TestDynamicForm.test_queryset_with_role:
- db: 'SELECT ... FROM "formidable_field" WHERE "formidable_field"."form_id" = # ORDER BY "formidable_field"."order" ASC'
- db: SELECT ... FROM "formidable_item" WHERE "formidable_item"."field_id" IN (...) ORDER BY "formidable_item"."order" ASC
- db: 'SELECT ... FROM "formidable_access" WHERE ("formidable_access"."access_id" = # AND "formidable_access"."field_id" IN (...))'
- db: SELECT ... FROM "formidable_validation" WHERE "formidable_validation"."field_id" IN (...)
- db: SELECT ... FROM "formidable_default" WHERE "formidable_default"."field_id" IN (...)
- db: 'SELECT ... FROM "formidable_preset" WHERE "formidable_preset"."form_id" = #'
TestDynamicForm.test_queryset_without_role:
- db: 'SELECT ... FROM "formidable_field" WHERE "formidable_field"."form_id" = # ORDER BY "formidable_field"."order" ASC'
- db: SELECT ... FROM "formidable_item" WHERE "formidable_item"."field_id" IN (...) ORDER BY "formidable_item"."order" ASC
- db: 'SELECT ... FROM "formidable_access" WHERE ("formidable_access"."access_id" = # AND "formidable_access"."field_id" IN (...))'
- db: SELECT ... FROM "formidable_validation" WHERE "formidable_validation"."field_id" IN (...)
- db: SELECT ... FROM "formidable_default" WHERE "formidable_default"."field_id" IN (...)
- db: 'SELECT ... FROM "formidable_preset" WHERE "formidable_preset"."form_id" = #'
35 changes: 34 additions & 1 deletion demo/tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
from django import forms
from django.core.exceptions import ValidationError
from django.test import TestCase
import django_perf_rec
from freezegun import freeze_time

from formidable.constants import REQUIRED, EDITABLE, READONLY, HIDDEN
from formidable.models import Formidable
from formidable.forms import widgets, fields
from formidable.forms import FormidableForm, widgets, fields


class TestDynamicForm(TestCase):
Expand Down Expand Up @@ -271,6 +272,38 @@ def test_hidden_field(self):
form = form_class()
self.assertNotIn('text-input', form.fields)

def test_queryset_with_role(self):
class MyForm(FormidableForm):
first_name = fields.CharField(default='foo')
last_name = fields.CharField(default='bar')
origin = fields.ChoiceField(
choices=(('fr', 'France'), ('en', 'England'))
)
weapons = fields.ChoiceField(
choices=(('gun', 'Gun'), ('sword', 'Sword'))
)

form = MyForm.to_formidable(label='test')

with django_perf_rec.record(path='perfs/'):
form.get_django_form_class(role='jedi')

def test_queryset_without_role(self):
class MyForm(FormidableForm):
first_name = fields.CharField(default='foo')
last_name = fields.CharField(default='bar')
origin = fields.ChoiceField(
choices=(('fr', 'France'), ('en', 'England'))
)
weapons = fields.ChoiceField(
choices=(('gun', 'Gun'), ('sword', 'Sword'))
)

form = MyForm.to_formidable(label='test')

with django_perf_rec.record(path='perfs/'):
form.get_django_form_class(role='jedi')


class TestFormValidation(TestCase):

Expand Down
15 changes: 13 additions & 2 deletions formidable/forms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
from collections import OrderedDict

from django import forms
from django.db.models import Prefetch

from formidable.forms import field_builder
from formidable.forms.validations.presets import presets_register
from formidable.models import Formidable
from formidable.models import Access, Formidable, Item


class FormidableBoundFieldCache(dict):
Expand Down Expand Up @@ -79,7 +80,17 @@ def get_dynamic_form_class(formidable, role=None, field_factory=None):
attrs = OrderedDict()
field_factory = field_factory or field_builder.FormFieldFactory()

for field in formidable.fields.order_by('order').all():
access_qs = Access.objects.all()
if role:
access_qs = access_qs.filter(access_id=role)

fields = formidable.fields.prefetch_related(
Prefetch('items', queryset=Item.objects.order_by('order')),
Prefetch('accesses', queryset=access_qs),
'validations', 'defaults'
)

for field in fields.order_by('order').all():
try:
form_field = field_factory.produce(field, role)
except field_builder.SkipField:
Expand Down
2 changes: 1 addition & 1 deletion formidable/forms/field_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, field):
self.validator_factory = self.validator_factory_class()

def build(self, role=None):
self.access = self.field.accesses.get(access_id=role) if role else None
self.access = self.field.accesses.all()[0] if role else None
field_class = self.get_field_class()
return field_class(**self.get_field_kwargs())

Expand Down