Add form and Add search
This commit is contained in:
parent
a3f3b49b2c
commit
e26eb50582
23
README.md
23
README.md
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
[wallaviso.com](http://wallaviso.com)
|
[wallaviso.com](http://wallaviso.com)
|
||||||
|
|
||||||
## Run
|
## Run (Ejecutar)
|
||||||
|
|
||||||
[EN] For the impatient, you can play with the finished exercise. You should download the code and execute the following commands.
|
[EN] For the impatient, you can play with the finished exercise. You should download the code and execute the following commands.
|
||||||
|
|
||||||
@ -29,4 +29,23 @@ python3 app.py
|
|||||||
|
|
||||||
[EN] Then open in your favorite browser, which will possibly be the fantastic Firefox, a new tab with [http://127.0.0.1:5000](http://127.0.0.1:5000)
|
[EN] Then open in your favorite browser, which will possibly be the fantastic Firefox, a new tab with [http://127.0.0.1:5000](http://127.0.0.1:5000)
|
||||||
|
|
||||||
[ES] Después abrir en tu navegador favorito, que posiblemente será el fantástico Firefox, una pestaña nueva con [http://127.0.0.1:5000](http://127.0.0.1:5000)
|
[ES] Después abrir en tu navegador favorito, que posiblemente será el fantástico Firefox, una pestaña nueva con [http://127.0.0.1:5000](http://127.0.0.1:5000)
|
||||||
|
|
||||||
|
## Workshop (Taller)
|
||||||
|
|
||||||
|
### Part 1 - Flask Core y Search (Parte 1 - Nucleo de Flask y Buscador) 50 min
|
||||||
|
|
||||||
|
### Break (Descanso) - 10 min
|
||||||
|
|
||||||
|
[EN] We debug bugs and prepare for the next point.
|
||||||
|
[ES] Depuramos bugs y nos preparamos para el siguiente punto.
|
||||||
|
|
||||||
|
### Part 2 - Databases and CRUD with Flask (Bases de datos y CRUD elementos con Flask)
|
||||||
|
|
||||||
|
### Break (Descanso) - 10 min
|
||||||
|
|
||||||
|
[EN] We take air for the last part. Otherwise, we make as we go to the bathroom and do not come back.
|
||||||
|
[ES] Cogemos aire para la última parte. En caso contrario, hacemos como que vamos al baño y nos piramos.
|
||||||
|
|
||||||
|
|
||||||
|
### Part 3 - Sending emails with new items (Envío de emails con nuevos elementos)
|
38
app.py
38
app.py
@ -1,10 +1,40 @@
|
|||||||
from flask import Flask, render_template
|
from flask import Flask, render_template, request
|
||||||
|
from forms import SearchForm
|
||||||
|
# Get data Wallapop
|
||||||
|
import json
|
||||||
|
from urllib3 import PoolManager
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
# Flask
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config['DEBUG'] = True
|
app.config['DEBUG'] = True
|
||||||
|
app.config['SECRET_KEY'] = 'mi secreto'
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET', 'POST'])
|
||||||
|
def buscador():
|
||||||
|
form = SearchForm()
|
||||||
|
results = None
|
||||||
|
if form.validate_on_submit():
|
||||||
|
name = form.name.data
|
||||||
|
price_max = form.price_max.data or ''
|
||||||
|
|
||||||
|
# Search in Wallapop
|
||||||
|
http = PoolManager()
|
||||||
|
url_api = 'http://es.wallapop.com/rest/items?minPrice=&maxPrice={price_max}&dist=&order=creationDate-des&lat=41.398077&lng=2.170432&kws={kws}'.format(
|
||||||
|
kws=urllib.parse.quote(name, safe=''),
|
||||||
|
price_max=price_max
|
||||||
|
)
|
||||||
|
results = http.request('GET', url_api)
|
||||||
|
results = json.loads(
|
||||||
|
results.data.decode('utf-8')
|
||||||
|
)
|
||||||
|
results = results['items']
|
||||||
|
return render_template('items/buscador.html', form=form, results=results)
|
||||||
|
|
||||||
|
@app.route('/programadas')
|
||||||
|
def programadas():
|
||||||
|
return render_template('items/programadas.html')
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
def index():
|
|
||||||
return render_template('items/buscador.html')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run()
|
app.run()
|
8
forms.py
Normal file
8
forms.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, IntegerField
|
||||||
|
from wtforms.validators import DataRequired, Length, NumberRange, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class SearchForm(FlaskForm):
|
||||||
|
name = StringField('Nombre', [Length(min=1, max=100, message='Es demasiado largo'), DataRequired(message='Campo obligatorio')])
|
||||||
|
price_max = IntegerField('Precio', [NumberRange(1, message='No puede ser inferior a 1'), Optional()])
|
@ -0,0 +1,3 @@
|
|||||||
|
Flask==0.12.2
|
||||||
|
Flask-WTF==0.14.2
|
||||||
|
urllib3==1.22
|
@ -1,13 +1,46 @@
|
|||||||
{% extends 'layouts/master.html' %}
|
{% extends 'layouts/master.html' %}
|
||||||
|
{% set active_page = "buscador" %}
|
||||||
{% block title %}Buscador{% endblock %}
|
{% block title %}Buscador{% endblock %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<h1>Buscador</h1>
|
<h1>Buscador</h1>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<form >
|
<form method="post">
|
||||||
<input type="text" id="nombre" class="form-control" name="nombre" placeholder="Buscar...">
|
{{ form.csrf_token }}
|
||||||
<input type="submit" class="form-control" value="Buscar">
|
{% for input in form %}
|
||||||
|
{% if input.type != 'CSRFTokenField' %}
|
||||||
|
<div class="form-group">
|
||||||
|
{# Label #}
|
||||||
|
{{ input.label }}
|
||||||
|
{# Input #}
|
||||||
|
{{ input(class="form-control") }}
|
||||||
|
{# Errors #}
|
||||||
|
{% if input.errors %}
|
||||||
|
<div class="has-error">
|
||||||
|
{% for error in input.errors %}
|
||||||
|
<label class="help-block">
|
||||||
|
{{ error }}
|
||||||
|
</label>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<input type="submit" class="btn btn-primary" value="Buscar">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if results %}
|
||||||
|
<table class="table">
|
||||||
|
{% for item in results %}
|
||||||
|
<tr>
|
||||||
|
<td><img class="img-responsive" src="{{ item.pictureURL }}" alt="{{ item.title }}"></td>
|
||||||
|
<td>{{ item.title }}</td>
|
||||||
|
<td>{{ item.price }}</td>
|
||||||
|
<td><a href="#" class="btn btn-success">+</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
6
templates/items/programadas.html
Normal file
6
templates/items/programadas.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% extends 'layouts/master.html' %}
|
||||||
|
{% set active_page = "programadas" %}
|
||||||
|
{% block title %}Programadas{% endblock %}
|
||||||
|
{% block body %}
|
||||||
|
<h1>Programadas</h1>
|
||||||
|
{% endblock %}
|
@ -8,6 +8,10 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<ul class="nav nav-pills nav-justified">
|
||||||
|
<li role="presentation" {% if active_page == "buscador" %}class="active"{% endif %}><a href="{{ url_for('buscador') }}">Buscador</a></li>
|
||||||
|
<li role="presentation" {% if active_page == "programadas" %}class="active"{% endif %}><a href="{{ url_for('programadas') }}">Programadas</a></li>
|
||||||
|
</ul>
|
||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
Loading…
Reference in New Issue
Block a user