librelist archives

« back to archive

Flask-WTFroms populate

Flask-WTFroms populate

From:
Christoph Blau
Date:
2014-07-09 @ 15:01
Hi List

I am a beginner, please bear with me! I am working on an app and was 
hoping for some help from the experts :-D

I have  a simple form:

class aForm(Form):
  type    = HiddenField('Type')
  regex   = re.compile('^[a-zA-Z0-9-]+$')
  record  = TextField('Hostname', validators =[Required(),Regexp(regex)])
  ttl     = TextField('TTL', validators =[Required()])
  content = TextField('Destination', validators =[Required(),IPAddress()])
  edit    = SubmitField('Update')

Here my route:

@app.route('/dns/<domain>', methods = ['GET', 'POST'])
def dnsDisplay(domain=None):
name='Zone Management'
domain = domain or request.args.get('domain')
Records = getRecords(domain)
aRecords=MultiDict()
for sublist in Records:
if sublist[0] == 'A':
aRecords.add('type', sublist[0])
aRecords.add('record',sublist[1])
aRecords.add('ttl',sublist[2])
aRecords.add('content',sublist[3])
print aRecords
form = aForm(request.form,**aRecords)
print form.errors
  return 
render_template('selected.html',title=domain,d=domain,a=aRecords,form=form)

The MultiDict looks like this

MultiDict([('type', 'A'), ('record', <DNS name ns1>), ('ttl', 3600L), 
('content',  '10.10.1.70'), ('type', 'A'), ('record', <DNS name ftp>), 
('ttl', 3600L), ('content', '10.10.1.65'), ('type', 'A'), ('record', <DNS 
name www>), ('ttl', 3600L), ('content', '10.10.1.69')])


Here is my template:

{% extends 'base.html' %}
{%block main%}

{% for message in form.record.errors %}
  <div id=flashes>
   {{ message }}
  </div>
{% endfor %}

<fieldset id=shadow>
  {% for item in form -%}
  <form action='' method=POST>
    {{form.hidden_tag()}}
    {{form.type(size=2)}}
    {{form.record(size=15)}}
    {{form.ttl(size=5)}}
    {{form.content(size=15)}}
    {{form.edit}}
  </form>
  {% endfor -%}
</fieldset>

{%endblock%}

The problem is that it only displays the first set of data and that 6 times?!

I tried a different unsuccessful approach with a collections.defaultdict 
that presents the data as such
defaultdict(<type 'list'>, {'content': ['10.10.1.70', '10.10.1.65', 
'10.10.1.69'], 'record': [<DNS name ns1>, <DNS name ftp>, <DNS name www>],
'type': ['A', 'A', 'A'], 'ttl': [3600L, 3600L, 3600L]})

Anyway... The result is supposed to look like the below with each line 
being a separate form.

ns1    3600  10.10.1.70  Update
ftp     3600  10.10.1.65  Update
www  3600  10.10.1.69  Update

I thought of a completely different approach where I would pass the 
aRecords data as a separate variable into the template and then loop 
through the aRecords data instead.

I am stuck and really need some advise please!

Many Thanks,
Christoph

Re: [flask] Flask-WTFroms populate

From:
Brice Leroy
Date:
2014-07-09 @ 15:49
Hi Christoph,

Have a look at FieldList:

http://wtforms.simplecodes.com/docs/0.6.1/fields.html#field-enclosures,

it allows you to create a field that handles a list of the same type.
Define one per type (type, record, ttl...). That should do it.

You might also want to validate that every fieldList have the same length ;)

Something like:

record  = FieldList(TextField('Hostname', validators=[...]), min_entries=1)
ttl     = FieldList(TextField('TTL', validators =[...], min_entries=1)
...


On Wed, Jul 9, 2014 at 8:01 AM, Christoph Blau <christoph@4dt.co.za> wrote:

>  Hi List
>
> I am a beginner, please bear with me! I am working on an app and was
> hoping for some help from the experts :-D
>
> I have  a simple form:
>
> class aForm(Form):
>   type    = HiddenField('Type')
>   regex   = re.compile('^[a-zA-Z0-9-]+$')
>   record  = TextField('Hostname', validators =[Required(),Regexp(regex)])
>   ttl     = TextField('TTL', validators =[Required()])
>   content = TextField('Destination', validators =[Required(),IPAddress()])
>   edit    = SubmitField('Update')
>
> Here my route:
>
> @app.route('/dns/<domain>', methods = ['GET', 'POST'])
> def dnsDisplay(domain=None):
> name='Zone Management'
> domain = domain or request.args.get('domain')
> Records = getRecords(domain)
> aRecords=MultiDict()
> for sublist in Records:
> if sublist[0] == 'A':
> aRecords.add('type', sublist[0])
> aRecords.add('record',sublist[1])
> aRecords.add('ttl',sublist[2])
> aRecords.add('content',sublist[3])
> print aRecords
> form = aForm(request.form,**aRecords)
> print form.errors
>   return
> render_template('selected.html',title=domain,d=domain,a=aRecords,form=form
> )
>
> The MultiDict looks like this
>
> MultiDict([('type', 'A'), ('record', <DNS name ns1>), ('ttl', 3600L),
> ('content',  '10.10.1.70'), ('type', 'A'), ('record', <DNS name ftp>),
> ('ttl', 3600L), ('content', '10.10.1.65'), ('type', 'A'), ('record', <DNS
> name www>), ('ttl', 3600L), ('content', '10.10.1.69')])
>
>
> Here is my template:
>
> {% extends 'base.html' %}
> {%block main%}
>
> {% for message in form.record.errors %}
>   <div id=flashes>
>    {{ message }}
>   </div>
> {% endfor %}
>
> <fieldset id=shadow>
>   {% for item in form -%}
>   <form action='' method=POST>
>     {{form.hidden_tag()}}
>     {{form.type(size=2)}}
>     {{form.record(size=15)}}
>     {{form.ttl(size=5)}}
>     {{form.content(size=15)}}
>     {{form.edit}}
>   </form>
>   {% endfor -%}
> </fieldset>
>
> {%endblock%}
>
> The problem is that it only displays the first set of data and that 6
> times?!
>
> I tried a different unsuccessful approach with a collections.defaultdict
> that presents the data as such
> defaultdict(<type 'list'>, {'content': ['10.10.1.70', '10.10.1.65',
> '10.10.1.69'], 'record': [<DNS name ns1>, <DNS name ftp>, <DNS name www>],
> 'type': ['A', 'A', 'A'], 'ttl': [3600L, 3600L, 3600L]})
>
> Anyway... The result is supposed to look like the below with each line
> being a separate form.
>
> ns1    3600  10.10.1.70  Update
> ftp     3600  10.10.1.65  Update
> www  3600  10.10.1.69  Update
>
> I thought of a completely different approach where I would pass the
> aRecords data as a separate variable into the template and then loop
> through the aRecords data instead.
>
> I am stuck and really need some advise please!
>
> Many Thanks,
> Christoph
>



-- 
Brice Leroy - SodaHead

Re: [flask] Flask-WTFroms populate

From:
Christoph Blau
Date:
2014-07-14 @ 07:29
Hi List

Many Thanks for you replies.

I have been playing around with the suggestions but have not yet found the
appropriate solution to my problem. I know I am not good in explaining 
things so I will give it a second go.

I have modified my route slightly to organize the data differently.

@app.route('/dns/<domain>', methods = ['GET', 'POST'])
def dnsDisplay(domain=None):
  name='Zone Management'
  domain = domain or request.args.get('domain')
  Records = getRecords(domain)
  aRecords=[]
  for sublist in Records:
    if sublist[0] == 'A':
      sub={
      'type':sublist[0],
      'record':sublist[1],
      'ttl':sublist[2],
      'content':sublist[3]
      }
      aRecords.append(sub)
  print aRecords
  form = aForm(request.form,aRecords)
  print form.errors
  return render_template('selected.html',title=domain,d=domain,a=form)

The resulting list of dicts is:

[
{'content': '10.10.1.70', 'record': <DNS name ns1>, 'type': 'A', 'ttl': 3600L},
{'content': '10.10.1.65', 'record': <DNS name ftp>, 'type': 'A', 'ttl': 3600L},
{'content': '10.10.1.69', 'record': <DNS name www>, 'type': 'A', 'ttl': 3600L}
]

The aim is to have each dict in a separate form... I hope this makes more sense.

here the template again

{% extends 'base.html' %}
{%block main%}

{% for message in a.errors %}
  <div id=flashes>
   {{ message }}
  </div>
{% endfor %}

<fieldset id=shadow>
    {{a.hidden_tag()}}
    {{a.type(size=2)}}
    {{a.record(size=15)}}
    {{a.ttl(size=5)}}
    {{a.content(size=15)}}
    {{a.edit}}
</fieldset>

{%endblock%}


At the moment my form is blank :-{{

Please... I am open  for suggestions!

Kind regards,
Christoph

-----Original Message-----
From: Marcel Radischat 
<m.radischat@gin-n.de<mailto:Marcel%20Radischat%20%3cm.radischat@gin-n.de%3e>>
To: christoph@4dt.co.za<mailto:christoph@4dt.co.za>
Cc: flask@librelist.com<mailto:flask@librelist.com>
Subject: Re: [flask] Flask-WTFroms populate
Date: Thu, 10 Jul 2014 11:32:17 +0200

Hi!

The problem is the following code in your template:

  {% for item in form -%}
  <form action='' method=POST>
    {{form.hidden_tag()}}
    {{form.type(size=2)}}
    {{form.record(size=15)}}
    {{form.ttl(size=5)}}
    {{form.content(size=15)}}
    {{form.edit}}
  </form>
  {% endfor -%}


You define the the loop with for item in form and then you print the form 
6 times, because you have 6 expressions in your loop. Just remove the loop
and you will be fine.

HTH Marcel On 09 Jul 2014, at 17:01, Christoph Blau 
<christoph@4dt.co.za<mailto:christoph@4dt.co.za>> wrote:
Hi List

I am a beginner, please bear with me! I am working on an app and was 
hoping for some help from the experts :-D

I have  a simple form:

class aForm(Form):
  type    = HiddenField('Type')
  regex   = re.compile('^[a-zA-Z0-9-]+$')
  record  = TextField('Hostname', validators =[Required(),Regexp(regex)])
  ttl     = TextField('TTL', validators =[Required()])
  content = TextField('Destination', validators =[Required(),IPAddress()])
  edit    = SubmitField('Update')

Here my route:

@app.route('/dns/<domain>', methods = ['GET', 'POST'])
def dnsDisplay(domain=None):
name='Zone Management'
domain = domain or request.args.get('domain')
Records = getRecords(domain)
aRecords=MultiDict()
for sublist in Records:
if sublist[0] == 'A':
aRecords.add('type', sublist[0])
aRecords.add('record',sublist[1])
aRecords.add('ttl',sublist[2])
aRecords.add('content',sublist[3])
print aRecords
form = aForm(request.form,**aRecords)
print form.errors
  return 
render_template('selected.html',title=domain,d=domain,a=aRecords,form=form)

The MultiDict looks like this

MultiDict([('type', 'A'), ('record', <DNS name ns1>), ('ttl', 3600L), 
('content',  '10.10.1.70'), ('type', 'A'), ('record', <DNS name ftp>), 
('ttl', 3600L), ('content', '10.10.1.65'), ('type', 'A'), ('record', <DNS 
name www>), ('ttl', 3600L), ('content', '10.10.1.69')])


Here is my template:

{% extends 'base.html' %}
{%block main%}

{% for message in form.record.errors %}
  <div id=flashes>
   {{ message }}
  </div>
{% endfor %}

<fieldset id=shadow>
  {% for item in form -%}
  <form action='' method=POST>
    {{form.hidden_tag()}}
    {{form.type(size=2)}}
    {{form.record(size=15)}}
    {{form.ttl(size=5)}}
    {{form.content(size=15)}}
    {{form.edit}}
  </form>
  {% endfor -%}
</fieldset>

{%endblock%}

The problem is that it only displays the first set of data and that 6 times?!

I tried a different unsuccessful approach with a collections.defaultdict 
that presents the data as such
defaultdict(<type 'list'>, {'content': ['10.10.1.70', '10.10.1.65', 
'10.10.1.69'], 'record': [<DNS name ns1>, <DNS name ftp>, <DNS name www>],
'type': ['A', 'A', 'A'], 'ttl': [3600L, 3600L, 3600L]})

Anyway... The result is supposed to look like the below with each line 
being a separate form.

ns1    3600  10.10.1.70  Update
ftp     3600  10.10.1.65  Update
www  3600  10.10.1.69  Update

I thought of a completely different approach where I would pass the 
aRecords data as a separate variable into the template and then loop 
through the aRecords data instead.

I am stuck and really need some advise please!

Many Thanks,
Christoph

Re: [flask] Flask-WTFroms populate

From:
Christoph Blau
Date:
2014-07-17 @ 08:43
Hey List

Just to report back - I have abandoned the idea of passing all the data as
an object to the form.
Basically I am passing the data as a separate object to the template and 
then loop through the data to generate multiple form.

views.py:
@app.route('/dns/<domain>', methods = ['GET', 'POST'])
def dnsDisplay(domain=None):
  name='Zone Management'
  domain = domain or request.args.get('domain')
  Records = getRecords(domain)
  aRecords=[]
  print type(aRecords)
  for sublist in Records:
    if sublist[0] == 'A':
      sub={
      'type':sublist[0],
      'record':sublist[1],
      'ttl':sublist[2],
      'content':sublist[3]
      }
      aRecords.append(sub)
  print aRecords
  aFrm = aForm(request.form)
  print aFrm.errors
  return 
render_template('selected.html',title=domain,d=domain,aFrm=aFrm,aRec=aRecords)

selected.html:
{% extends 'base.html' %}
{%block main%}

{% for message in aFrm.errors %}
  <div id=flashes>
   {{ message }}
  </div>
{% endfor %}

<fieldset id=shadow>
  {%for a in aRec%}
    <form method=POST action=. name={{a.record}}>
     {{aFrm.hidden_tag()}}
     {{aFrm.type(size=2,value=a.type)}}
     {{aFrm.record(size=15,value=a.record)}}
     {{aFrm.ttl(size=5,value=a.ttl)}}
     {{aFrm.content(size=15,value=a.content)}}
     {{aFrm.edit}}
   </form>
  {%endfor%}
</fieldset>

{%endblock%}

The list that I am sending looks still like this:

[
{'content': '10.10.1.70', 'record': <DNS name ns1>, 'type': 'A', 'ttl': 3600L},
{'content': '10.10.1.65', 'record': <DNS name ftp>, 'type': 'A', 'ttl': 3600L},
{'content': '10.10.1.69', 'record': <DNS name www>, 'type': 'A', 'ttl': 3600L}
]

..and I end up with three separate forms that look like the below.

<form name="ns1" action="." method="POST">
    <div style="display:none;"></div>
    <input id="type" type="hidden" value="A" size="2" name="type"></input>
    <input id="record" type="text" value="ns1" size="15" name="record"></input>
    <input id="ttl" type="text" value="3600" size="5" name="ttl"></input>
    <input id="content" type="text" value="10.10.1.70" size="15" 
name="content"></input>
    <input id="edit" type="submit" value="Update" name="edit"></input>
</form>

Kind regards,
Christoph


-----Original Message-----
From: Christoph Blau 
<christoph@4dt.co.za<mailto:Christoph%20Blau%20%3cchristoph@4dt.co.za%3e>>
Reply-to: <flask@librelist.com>
To: flask@librelist.com<mailto:flask@librelist.com>
Subject: Re: [flask] Flask-WTFroms populate
Date: Mon, 14 Jul 2014 07:29:47 +0000

Hi List

Many Thanks for you replies.

I have been playing around with the suggestions but have not yet found the
appropriate solution to my problem. I know I am not good in explaining 
things so I will give it a second go.

I have modified my route slightly to organize the data differently.

@app.route('/dns/<domain>', methods = ['GET', 'POST'])
def dnsDisplay(domain=None):
  name='Zone Management'
  domain = domain or request.args.get('domain')
  Records = getRecords(domain)
  aRecords=[]
  for sublist in Records:
    if sublist[0] == 'A':
      sub={
      'type':sublist[0],
      'record':sublist[1],
      'ttl':sublist[2],
      'content':sublist[3]
      }
      aRecords.append(sub)
  print aRecords
  form = aForm(request.form,aRecords)
  print form.errors
  return render_template('selected.html',title=domain,d=domain,a=form)

The resulting list of dicts is:

[
{'content': '10.10.1.70', 'record': <DNS name ns1>, 'type': 'A', 'ttl': 3600L},
{'content': '10.10.1.65', 'record': <DNS name ftp>, 'type': 'A', 'ttl': 3600L},
{'content': '10.10.1.69', 'record': <DNS name www>, 'type': 'A', 'ttl': 3600L}
]

The aim is to have each dict in a separate form... I hope this makes more sense.

here the template again

{% extends 'base.html' %}
{%block main%}

{% for message in a.errors %}
  <div id=flashes>
   {{ message }}
  </div>
{% endfor %}

<fieldset id=shadow>
    {{a.hidden_tag()}}
    {{a.type(size=2)}}
    {{a.record(size=15)}}
    {{a.ttl(size=5)}}
    {{a.content(size=15)}}
    {{a.edit}}
</fieldset>

{%endblock%}


At the moment my form is blank :-{{

Please... I am open  for suggestions!

Kind regards,
Christoph

-----Original Message-----
From: Marcel Radischat 
<m.radischat@gin-n.de<mailto:Marcel%20Radischat%20%3cm.radischat@gin-n.de%3e>>
To: christoph@4dt.co.za<mailto:christoph@4dt.co.za>
Cc: flask@librelist.com<mailto:flask@librelist.com>
Subject: Re: [flask] Flask-WTFroms populate
Date: Thu, 10 Jul 2014 11:32:17 +0200

Hi!

The problem is the following code in your template:

  {% for item in form -%}
  <form action='' method=POST>
    {{form.hidden_tag()}}
    {{form.type(size=2)}}
    {{form.record(size=15)}}
    {{form.ttl(size=5)}}
    {{form.content(size=15)}}
    {{form.edit}}
  </form>
  {% endfor -%}


You define the the loop with for item in form and then you print the form 
6 times, because you have 6 expressions in your loop. Just remove the loop
and you will be fine.

HTH Marcel On 09 Jul 2014, at 17:01, Christoph Blau 
<christoph@4dt.co.za<mailto:christoph@4dt.co.za>> wrote:
Hi List

I am a beginner, please bear with me! I am working on an app and was 
hoping for some help from the experts :-D

I have  a simple form:

class aForm(Form):
  type    = HiddenField('Type')
  regex   = re.compile('^[a-zA-Z0-9-]+$')
  record  = TextField('Hostname', validators =[Required(),Regexp(regex)])
  ttl     = TextField('TTL', validators =[Required()])
  content = TextField('Destination', validators =[Required(),IPAddress()])
  edit    = SubmitField('Update')

Here my route:

@app.route('/dns/<domain>', methods = ['GET', 'POST'])
def dnsDisplay(domain=None):
name='Zone Management'
domain = domain or request.args.get('domain')
Records = getRecords(domain)
aRecords=MultiDict()
for sublist in Records:
if sublist[0] == 'A':
aRecords.add('type', sublist[0])
aRecords.add('record',sublist[1])
aRecords.add('ttl',sublist[2])
aRecords.add('content',sublist[3])
print aRecords
form = aForm(request.form,**aRecords)
print form.errors
  return 
render_template('selected.html',title=domain,d=domain,a=aRecords,form=form)

The MultiDict looks like this

MultiDict([('type', 'A'), ('record', <DNS name ns1>), ('ttl', 3600L), 
('content',  '10.10.1.70'), ('type', 'A'), ('record', <DNS name ftp>), 
('ttl', 3600L), ('content', '10.10.1.65'), ('type', 'A'), ('record', <DNS 
name www>), ('ttl', 3600L), ('content', '10.10.1.69')])


Here is my template:

{% extends 'base.html' %}
{%block main%}

{% for message in form.record.errors %}
  <div id=flashes>
   {{ message }}
  </div>
{% endfor %}

<fieldset id=shadow>
  {% for item in form -%}
  <form action='' method=POST>
    {{form.hidden_tag()}}
    {{form.type(size=2)}}
    {{form.record(size=15)}}
    {{form.ttl(size=5)}}
    {{form.content(size=15)}}
    {{form.edit}}
  </form>
  {% endfor -%}
</fieldset>

{%endblock%}

The problem is that it only displays the first set of data and that 6 times?!

I tried a different unsuccessful approach with a collections.defaultdict 
that presents the data as such
defaultdict(<type 'list'>, {'content': ['10.10.1.70', '10.10.1.65', 
'10.10.1.69'], 'record': [<DNS name ns1>, <DNS name ftp>, <DNS name www>],
'type': ['A', 'A', 'A'], 'ttl': [3600L, 3600L, 3600L]})

Anyway... The result is supposed to look like the below with each line 
being a separate form.

ns1    3600  10.10.1.70  Update
ftp     3600  10.10.1.65  Update
www  3600  10.10.1.69  Update

I thought of a completely different approach where I would pass the 
aRecords data as a separate variable into the template and then loop 
through the aRecords data instead.

I am stuck and really need some advise please!

Many Thanks,
Christoph