2014-04-25 2 views
0

같은 페이지에 렌더링되는 두 가지 양식의 숨겨진 필드가 있습니다. 이 숨겨진 필드의 default 설정은 true입니다. 나는 숨겨진 필드를 사용하여 제출 된 양식을 테스트합니다. 제출 된 양식의 해당 필드 값은 true으로 설정되고 다른 필드는 설정되지 않습니다.다른 양식이 제출 된 후 숨겨진 양식이 기본값을 유지하지 않습니다.

그러나 한 양식을 제출하면 (각 양식의 동작이 같은 페이지 임) 다른 필드의 숨겨진 필드 value이 비어있게 설정됩니다. 예를 들어 처음에

, 렌더링 필드가 (물론, 자신의 형태로 각)이 같다 : 내가 처음 양식을 제출하면

<input id="upload-submitted" name="upload-submitted" type="hidden" value="true"> 

...other stuff... 

<input id="process-submitted" name="process-submitted" type="hidden" value="true"> 

, 그것은 같은 날 할게요 페이지 및 필드는 다음과 같이 표현된다 : 나는 두 번째 양식을 제출하면

<input id="upload-submitted" name="upload-submitted" type="hidden" value="true"> 

...other stuff... 

<input id="process-submitted" name="process-submitted" type="hidden" value=""> 

후 모든 것이 더 value이없고 두 번째는 올바른 값을 갖는 첫 번째 input 제외하고는 동일합니다.

문제는 제출 후 구체 양식이 제출되지 않으면 submitted 필드의 data 필드가 비어있는 것 같습니다. 이것이 의미가 있습니다. 이것이 내가 실제로 제출 된 양식을 결정할 수있게합니다. 그러나 필드는 HTML의 렌더링을 위해 재설정되지 않습니다. 즉, 다른 양식을 제출 한 후에 다른 양식을 제출할 수 없음을 의미합니다.

어떻게 이런 일이 발생하지 않도록 할 수 있습니까? 한 페이지에 두 가지 양식 중 어떤 양식을 제출했는지 확인하는 더 좋은 방법이 있습니까?

class HiddenSubmitted(object): 
    """A mixin to provide a hidden field called "submitted" which has a default 
    value of "true". 
    """ 

    submitted = HiddenField(default="true") 

class ButtonWidget(object): 
    """A widget to conveniently display buttons. 
    """ 
    def __call__(self, field, **kwargs): 
     if field.name is not None: 
      kwargs.setdefault('name', field.name) 
     if field.value is not None: 
      kwargs.setdefault('value', field.value) 
     kwargs.setdefault('type', "submit") 
     return HTMLString('<button %s>%s</button>' % (
      html_params(**kwargs), 
      escape(field._value()) 
      )) 

class ButtonField(Field): 
    """A field to conveniently use buttons in flask forms. 
    """ 
    widget = ButtonWidget() 

    def __init__(self, text=None, name=None, value=None, **kwargs): 
     super(ButtonField, self).__init__(**kwargs) 
     self.text = text 
     self.value = value 
     if name is not None: 
      self.name = name 

    def _value(self): 
     return str(self.text) 

class MultiCheckboxField(SelectMultipleField): 
    """ 
    A multiple-select, except displays a list of checkboxes. 

    Iterating the field will produce subfields, allowing custom rendering of 
    the enclosed checkbox fields. 
    """ 
    widget = ListWidget(prefix_label=False) 
    option_widget = CheckboxInput() 

class DocumentUploadForm(Form, HiddenSubmitted): 
    """This is a form to upload files to the server. It handles both XML 
    and JSON files, and is used by the document_upload view. 
    """ 

    upload_button = ButtonField(text="Upload", name="action") 

    uploaded_file = FileField("File", validators=[ 
     FileRequired("You must select a file"), 
     FileAllowed(app.config["ALLOWED_EXTENSIONS"]) 
     ]) 

class ProcessForm(Form, HiddenSubmitted): 
    """ 
    Allows the user to select which objects should be 
    processed/deleted/whatever. 
    """ 

    PROCESS = "0" 
    DELETE = "-1" 

    files = MultiCheckboxField("Select", coerce=int, validators=[ 
     Required("You must select at least one item from the table.") 
     ]) 
    process_button = ButtonField("Process", name="action", value=PROCESS) 
    delete_button = ButtonField("Delete", name="action", value=DELETE) 

    def validate_files(form, field): 
     if form.process_button.data == form.PROCESS: 
      # There must be a JSON file selected 
      struc_count = 0 
      doc_count = 0 
      for selected_file in form.files.data: 
       unit = session.query(Unit).\ 
        filter(Unit.id == selected_file).one() 
       ext = os.path.splitext(unit.path)[1][1:] 
       if ext in app.config["STRUCTURE_EXTENSION"]: 
        struc_count += 1 
       else: 
        doc_count += 1 
      if struc_count is not 1: 
       raise ValidationError("Must be exactly one structure file") 
      if doc_count < 1: 
       raise ValidationError("At least one document must be selected") 

그리고 내 views.py :

process_button.submitted.data = "true" 
delete_button.submitted.data = "true" 
+0

:

def really_submitted(form): """ WTForms can be really finnicky when it comes to checking if a form has actually been submitted, so this method runs validate_on_submit() on the given form and checks if its "submitted" field has any data. Useful for pages that have two forms on them. :arg Form form: A form to check for submission. :returns boolean: True if submitted, false otherwise. """ if form.submitted.data == "true": return form.validate_on_submit() return False @app.route(app.config["PROJECT_ROUTE"] + "<project_id>", methods=["GET", "POST"]) def project_show(project_id): """ Show the files contained in a specific project. It also allows the user to upload a new document, much like projects(). :param int project_id: The ID of the desired project. """ upload_form = forms.DocumentUploadForm(prefix="upload") process_form = forms.ProcessForm(prefix="process") # If I put a print statement here, I find that by now one field has no data for the hidden field, which makes sense # The template needs access to the ID of each file and its filename. process_form.files.choices = [] file_objects = #blah blah database stuff # First handle the actions of the upload form if shortcuts.really_submitted(upload_form): uploaded_files = request.files.getlist("upload-uploaded_file") for uploaded_file in uploaded_files: filename = secure_filename(uploaded_file.filename) dest_path = os.path.join(app.config["UPLOAD_DIR"], str(project_id), filename) uploaded_file.save(dest_path) unit = Unit(path=dest_path, project=project_id) unit.save() process_form.files.choices.append((unit.id, os.path.split(dest_path)[1])) # Or what happened with the document selection elif shortcuts.really_submitted(process_form): files = request.form.getlist("process-files") if request.form["action"] == process_form.DELETE: # Delete every selected file, its database record, and item in # the listing for file_id in files: file_model = session.query(Unit).\ filter(Unit.id == file_id).one() file_name = os.path.split(file_model.path)[1] os.remove(file_model.path) session.delete(file_model) session.commit() process_form.files.choices.remove((int(file_id), file_name)) elif request.form["action"] == process_form.PROCESS: #TODO: process these files. pass return render_template("document_list.html", upload_form=upload_form, process_form=process_form) 
dirn

+0

좋아요, 그럼 어떻게해야합니까? 유효성 검사와 검사 후에'data' 필드를 수동으로 재설정 할 수 있습니까? – Plasma

답변

0

는 적어도, 하나 개의 솔루션이 바로 템플릿을 렌더링하기 전에,이 여기있다

내 forms.py입니다 양식은 [기본적으로 요청에 의해 자동으로 채워집니다] (https://github.com/lepture/flask-wtf/blob/master/flask_wtf/form.py#L71-L73).
관련 문제