View.py
@login_required
@access_required("reporter")
def create_custom_report(request, report_id=None):
"""
The user can create a report that fill fetch data from the model
he has choosen.
"""
return render(request, 'reports/create_custom_report.html', locals())
Forms.py
class ModelPickerForm(forms.Form):
"""
This form is used by the CustomReportFormWizard.
It list all models from settings.CUSTOM_REPORT_DATA_SOURCES
and create a checkbox for each of them, letting the user choose
which models he wants the report to extract data from.
"""
report_name = forms.CharField()
def __init__(self, *args, **kwargs):
self.wizard = kwargs.pop('wizard', None)
super(ModelPickerForm, self).__init__(*args, **kwargs)
for model_name in DATA_SOURCES:
tab_label = DATA_SOURCE_ORDER[model_name]
self.fields[model_name] = forms.BooleanField(required=False,label=tab_label)
def get_helper(self):
"""
Return the django-uni-form helper that formats the form so the
fields are in the proper order and grouped by div for step form.
The inversion of h2 and h3 is because of design legacy
"""
helper = FormHelper()
helper.form_class = "hive-form"
helper.form_tag = False
return helper
class FieldPickerForm(forms.Form):
"""
This form is used by the CustomReportFormWizard.
Given the user selection recorded with the ModelPickerForm,
this forms let the user selects the fields for each model
he/she wants to filter.
The forms take all the models, list the fields, and create
form fields for each of them.
"""
FIELD_TYPES = (models.CharField,
models.DateField,
models.DateTimeField,
models.IntegerField,
models.PositiveIntegerField,
models.SmallIntegerField,
models.PositiveSmallIntegerField,
models.BooleanField)
def __init__(self, *args, **kwargs):
"""
Create a form field object for each field of each selected model
"""
self.wizard = kwargs.pop('wizard',None)
super(FieldPickerForm, self).__init__(*args, **kwargs)
prev_form = self.wizard.field_selector_form
self.models = SortedDict()
if prev_form.is_valid():
self.model_list = [name for name, on in self.wizard.model_picker_form.cleaned_data.items() if on]
self.model_list.remove('report_name')
for model_name in self.model_list:
self.models[model_name] = []
fields = DATA_SOURCES[model_name]._meta.fields
fields = (f for f in fields if self.is_filter_field(f))
for field in fields:
#print field.name
if isinstance(field, models.BooleanField):
form_field = forms.TypedChoiceField()
form_field.choices = ((1, 'Yes'), (0, 'No'))
elif isinstance(field, models.DateTimeField):
form_field = DateTimeRangeField()
elif isinstance(field, models.DateField):
form_field = DateRangeField()
else:
form_field = field.formfield()
if (isinstance(form_field, forms.TypedChoiceField)
and form_field.choices[0][1] != '---------'):
form_field.choices.insert(0, ('', '---------'))
form_field.initial = None
form_field.default = None
form_field.required = False
field_name = '%s__%s' % (model_name, field.name)
if field.name in OR_FIELD:
if field.name=='icd10_code' and (model_name == 'services__Linkage' or model_name == 'services__Referral'):
choice_data=get_field_value('organization')
model_name_new = '%s__%s' % (model_name, 'organization_id')
self.fields[model_name_new]=forms.MultipleChoiceField(choices = choice_data,required = False)
self.models[model_name].append(model_name_new)
else:
if field.name=='referral_type' and model_name=='services__Referral':
choice_data=get_field_value('referral_type_referral')
model_name_r = '%s__%s' % (model_name, 'referral_type')
self.fields[model_name_r]=forms.MultipleChoiceField(choices = choice_data,required = False)
self.models[model_name].append(model_name_r)
else:
if field.name!='icd10_code':
choice_data=get_field_value(field.name)
self.fields[field_name]=forms.MultipleChoiceField(choices = choice_data,required = False)
self.models[model_name].append(field_name)
else:
self.fields[field_name]=form_field
self.models[model_name].append(field_name)
@classmethod
def is_filter_field(cls, field):
#import pdb;pdb.set_trace()
allowed_type = any(isinstance(field, ftype) for ftype in cls.FIELD_TYPES)
#if not isinstance(field, (models.DateTimeField, models.DateField, models.BooleanField)):
#allowed_type = bool(field.choices)
return allowed_type
def get_helper(self):
"""
Return the django-uni-form helper that formats the form so the
fields are in the proper order and grouped by div for step form.
The inversion of h2 and h3 is because of design legacy
"""
helper = FormHelper()
box_list = []
for i, model in enumerate(self.models.iteritems()):
field_names = model[1]
model_name = model[0].split('__')[-1]
box = MultiField(
u'<h3>%s</h3>' % model_name,
Div(
*field_names,
css_class='form-step-content' + " show" * (i == 0)
),
css_id="step%s" % i,
css_class="form-step"
)
box_list.append(box)
layout = Layout(*box_list)
helper.form_class = "hive-form"
helper.add_layout(layout)
helper.form_tag = False
return helper
class FieldSelectorForm(forms.Form):
"""
This form is used by the CustomReportFormWizard.
Given the user selection recorded with the ModelPickerForm,
this forms let the user selects the fields for each model
he/she wants to filter.
The forms take all the models, list the fields, and create
form fields for each of them.
"""
FIELD_TYPES = (models.CharField,
models.DateField,
models.DateTimeField,
models.IntegerField,
models.PositiveIntegerField,
models.SmallIntegerField,
models.PositiveSmallIntegerField,
models.BooleanField)
def __init__(self, *args, **kwargs):
"""
Create a form field object for each field of each selected model
"""
#import pdb; pdb.set_trace()
self.wizard = kwargs.pop('wizard')
super(FieldSelectorForm, self).__init__(*args, **kwargs)
prev_form_1 = self.wizard.model_picker_form
self.models = SortedDict()
if prev_form_1.is_valid():
self.model_list = [name for name, on in prev_form_1.cleaned_data.items() if on]
self.model_list.remove('report_name')
print len(self.model_list)
for model_name in self.model_list:
self.models[model_name] = []
fields = DATA_SOURCES[model_name]._meta.fields
fields = (f for f in fields if self.is_filter_field(f))
for field in fields:
#print field.name
if isinstance(field, models.BooleanField):
form_field = forms.TypedChoiceField()
form_field.choices = ((1, 'Yes'), (0, 'No'))
elif isinstance(field, models.DateTimeField):
form_field = DateTimeRangeField()
elif isinstance(field, models.DateField):
form_field = DateRangeField()
else:
form_field = field.formfield()
if (isinstance(form_field, forms.TypedChoiceField)
and form_field.choices[0][1] != '---------'):
form_field.choices.insert(0, ('', '---------'))
form_field.initial = None
form_field.default = None
form_field.required = False
field_name = '%s__%s' % (model_name, field.name)
#self.fields[field_name] = form_field
self.fields[field_name] = forms.BooleanField(required=False)
self.models[model_name].append(field_name)
@classmethod
def is_filter_field(cls, field):
#import pdb;pdb.set_trace()
allowed_type = any(isinstance(field, ftype) for ftype in cls.FIELD_TYPES)
#if not isinstance(field, (models.DateTimeField, models.DateField, models.BooleanField)):
#allowed_type = bool(field.choices)
return allowed_type
def get_helper(self):
"""
Return the django-uni-form helper that formats the form so the
fields are in the proper order and grouped by div for step form.
The inversion of h2 and h3 is because of design legacy
"""
helper = FormHelper()
box_list = []
for i, model in enumerate(self.models.iteritems()):
field_names = model[1]
model_name = model[0].split('__')[-1]
box = MultiField(
u'<h3>%s</h3>' % model_name,
Div(
*field_names,
css_class='form-step-content' + " show" * (i == 0)
),
css_id="step%s" % i,
css_class="form-step"
)
box_list.append(box)
layout = Layout(*box_list)
helper.form_class = "hive-form"
helper.add_layout(layout)
helper.form_tag = False
return helper
class CustomReportFormWizard(FormWizard):
"""
Two step form:
- first the user select models with ModelPickerForm
- secondly the user choose field to filter from FieldPickerForm
When saving, a custom report object is created with
holding a dictionary which maps all the selected model.field
with the value it should us as a filter.
"""
def done(self, request, form_list):
print '######################################################################'
model_form, select_form,field_form = form_list
query = SortedDict()
for field_name in field_form.fields:
app, model, field = field_name.split('__')
name = '%s__%s' % (model, field)
value = field_form.cleaned_data[field_name]
if value or value == 0:
query[name] = value
query['data_model_name'] = [model.split('__')[1] for model in field_form.model_list]
temp=SortedDict()
new_model = {}
for field_name in select_form.fields:
app, model, field = field_name.split('__')
name = '%s__%s' % (model, field)
value = select_form.cleaned_data[field_name]
if model in new_model:
if value == True:
field_table = COM_MODEL_TABLE[model]+'.'+field
new_model[model].append(field_table)
else:
if value == True:
field_table = COM_MODEL_TABLE[model]+'.'+field
new_model[model]=[field_table]
#Strnigify the Sorted dict values
for key, value in new_model.items():
new_model[key] = ','.join(new_model[key])
#Done
query['select_field_name'] = new_model
CustomReport.objects.create(name=model_form.cleaned_data['report_name'],
query=json.dumps(query, indent=4,
default=serialize_datetime))
messages.success(request, "The report has been created successfully")
return redirect('custom-reports')
def get_template(self, step):
return "reports/create_custom_report.html"
def parse_params(self, request, *args, **kwargs):
"""
Add previous form result to history.
"""
#import pdb; pdb.set_trace()
if self.step==0:
self.model_picker_form = self.get_form(0, request.POST or None)
if self.step==1:
self.field_selector_form = self.get_form(1, request.POST or None)
@property
def previous_form(self):
if self.step:
return self.history[self.step - 1]
def get_form(self, step, data=None):
"""
Override to pass instance of the wizard to the form.
"""
"""
if step == 0:
if hasattr(self, 'model_picker_form'):
if self.model_picker_form.is_bound:
return self.model_picker_form
if step == 1:
if hasattr(self, 'field_picker_form'):
if self.field_picker_form.is_bound:
return self.field_picker_form
"""
obj = self.form_list[step](data,
prefix=self.prefix_for_step(step),
initial=self.initial.get(step, None),
wizard=self)
return obj
有三个步骤: 1.模型选择器 2.场地选择器 3.字段选择器
我将第1步数据传递到第2步和第3步。 在第1步:我正在选择表格 在步骤2中:显示所选表的所有列 在步骤3中:显示所选表中字段的过滤器逻辑。
它在python运行服务器中工作正常但有时它显示以前选择的表字段。 当我尝试使用apache服务器时。当我提交第2步然后我得到以下异常时,第1步和第2步工作正常。
AttributeError at /rep-datas/custom/create/
'CustomReportFormWizard' object has no attribute 'field_selector_form'
Request Method: POST
Request URL: http://54.80.181.207/rep-datas/custom/create/
Django Version: 1.3.1
Exception Type: AttributeError
Exception Value:
'CustomReportFormWizard' object has no attribute 'field_selector_form'
Exception Location: /var/www/stacks/django-apps/myproject/apps/rep-datas/forms.py in __init__, line 493
Python Executable: /usr/bin/python
Python Version: 2.6.6
Python Path:
['/var/www/stacks/django-apps/myproject/apps',
'/usr/lib/python2.6/site-packages/PIL-1.1.7-py2.6-linux-x86_64.egg',
'/usr/lib64/python26.zip',
'/usr/lib64/python2.6',
'/usr/lib64/python2.6/plat-linux2',
'/usr/lib64/python2.6/lib-tk',
'/usr/lib64/python2.6/lib-old',
'/usr/lib64/python2.6/lib-dynload',
'/usr/lib64/python2.6/site-packages',
'/usr/lib/python2.6/site-packages',
'/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg-info',
'/var/www/stacks/django-apps/']