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

2024-04-25 19:51:20 发布

您现在位置:Python中文网/ 问答频道 /正文

你知道吗视图.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())

你知道吗表单.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字段选择器 三。字段选择器

我将步骤1数据传递到步骤2和步骤3。 在步骤1中:我正在选择表 在步骤2中:显示所选表的所有列 在步骤3:显示选定表中字段的筛选逻辑。你知道吗

它在python运行服务器中运行良好,但有时显示先前选择的表字段。 当我尝试使用apache服务器时。第一步和第二步工作正常,当我提交第二步,然后我得到以下例外。你知道吗

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

Tags: thenameinselfformhelperfieldfields