当我将步骤2移至步骤3时,FormWizard正在创建问题

时间:2014-08-25 07:52:42

标签: python django

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/']

0 个答案:

没有答案