From 7c069dc2e4b64ec709343af0b3d9ff51f4b96bbe Mon Sep 17 00:00:00 2001 From: Rafael Henrique da Silva Correia Date: Tue, 29 Nov 2016 08:54:06 -0200 Subject: [PATCH 1/8] Fix link of travis badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8b87d2..8187b05 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/rafaelhenrique/flask_tutorial.svg?branch=master)](https://travis-ci.org/rafaelhenrique/flask_tutorial) +[![Build Status](https://travis-ci.org/python-sorocaba/flask_tutorial.svg?branch=master)](https://travis-ci.org/python-sorocaba/flask_tutorial) # Flask Tutorial From 70a27c1f49c8ec9de76bb7b7f7344f2b97d00a20 Mon Sep 17 00:00:00 2001 From: Rafael Henrique da Silva Correia Date: Wed, 7 Dec 2016 21:52:01 -0200 Subject: [PATCH 2/8] Add explanation how to run queries manually --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index 8187b05..2bbbf4c 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,34 @@ $ python manage.py runserver More information? Follow explanatory videos below. +## How to execute queries manually? + +Inside on your virtualenv: +``` +$ python manage.py shell +``` + +Import db and model: +``` +from tvseries.ext import db +from tvseries.core.models import TVSerie +``` + +Bind your session with your application: +``` +db.app = app +``` + +Quering example: +``` +db.session.query(TVSerie).all() +``` + +If operation is "create", "update" or "delete" dont forget to run commit operation to confirm operation: +``` +db.session.commit() +``` + ## 1.0 - Flask and the most basic application of the world! - See release code: https://github.com/rafaelhenrique/flask_tutorial/tree/1.0 From fcff27c9f5a8f58512bd584ac5b2c6ff78414287 Mon Sep 17 00:00:00 2001 From: Rafael Henrique da Silva Correia Date: Wed, 7 Dec 2016 23:31:02 -0200 Subject: [PATCH 3/8] Implements CSRF verification --- tvseries/__init__.py | 3 ++- tvseries/config.py | 2 ++ tvseries/ext.py | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tvseries/__init__.py b/tvseries/__init__.py index eeda833..4f1a4a1 100644 --- a/tvseries/__init__.py +++ b/tvseries/__init__.py @@ -1,7 +1,7 @@ from flask import Flask from tvseries import config -from tvseries.ext import db +from tvseries.ext import db, csrf from tvseries.core import core_blueprint @@ -10,4 +10,5 @@ def create_app(config=config.ProductionConfig): app.config.from_object(config) app.register_blueprint(core_blueprint, url_prefix='/') db.init_app(app) + csrf.init_app(app) return app diff --git a/tvseries/config.py b/tvseries/config.py index daa8efb..3d13fd4 100644 --- a/tvseries/config.py +++ b/tvseries/config.py @@ -11,6 +11,7 @@ class BaseConfig(object): SQLALCHEMY_TRACK_MODIFICATIONS = True COLLECT_STATIC_ROOT = os.path.join(BASE_DIR, "static") COLLECT_STORAGE = 'flask_collect.storage.file' + WTF_CSRF_ENABLED = True DEBUG = False TESTING = False @@ -22,6 +23,7 @@ class DevelopmentConfig(BaseConfig): class TestConfig(BaseConfig): SQLALCHEMY_DATABASE_URI = 'sqlite:///tvseries-test.sqlite3' TESTING = True + WTF_CSRF_ENABLED = False class ProductionConfig(BaseConfig): diff --git a/tvseries/ext.py b/tvseries/ext.py index f0b13d6..1007acf 100644 --- a/tvseries/ext.py +++ b/tvseries/ext.py @@ -1,3 +1,5 @@ from flask_sqlalchemy import SQLAlchemy +from flask_wtf.csrf import CsrfProtect db = SQLAlchemy() +csrf = CsrfProtect() From 0f588dfded13fa1dffc472698799ff53419dc484 Mon Sep 17 00:00:00 2001 From: Rafael Henrique da Silva Correia Date: Thu, 8 Dec 2016 00:37:30 -0200 Subject: [PATCH 4/8] Implements TVSerieForm using Flask-WTF --- requirements.txt | 1 + tvseries/core/forms.py | 10 ++++++ tvseries/core/templates/add.html | 53 ++++++++++++++++++++++++++++---- tvseries/core/views.py | 20 ++++++------ tvseries/tests/test_core.py | 28 ++++++++++++----- tvseries/tests/test_forms.py | 38 +++++++++++++++++++++++ 6 files changed, 128 insertions(+), 22 deletions(-) create mode 100644 tvseries/core/forms.py create mode 100644 tvseries/tests/test_forms.py diff --git a/requirements.txt b/requirements.txt index ef7c4a9..e909afc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ Flask-Collect==1.3.2 ansible==2.2.0.0 Flask-Migrate==2.0.1 psycopg2==2.6.2 +Flask-WTF==0.13.1 diff --git a/tvseries/core/forms.py b/tvseries/core/forms.py new file mode 100644 index 0000000..dccd3d0 --- /dev/null +++ b/tvseries/core/forms.py @@ -0,0 +1,10 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, DateField + + +class TVSerieForm(FlaskForm): + name = StringField('name') + description = StringField('description') + episodies_number = StringField('episodies_number') + author = StringField('author') + year = DateField('year') diff --git a/tvseries/core/templates/add.html b/tvseries/core/templates/add.html index ff38af4..2d7fca6 100644 --- a/tvseries/core/templates/add.html +++ b/tvseries/core/templates/add.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% block content %} -
+ + {{ form.csrf_token }}
Adicionar série de TV
@@ -8,20 +9,60 @@
- + {{ form.name }} + {% if form.name.errors %} +
    + {% for error in form.name.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %}
- + {{ form.description }} + {% if form.description.errors %} +
    + {% for error in form.description.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %}
- + {{ form.author }} + {% if form.author.errors %} +
    + {% for error in form.author.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %}
- -
+ {{ form.episodies_number }} + {% if form.episodies_number.errors %} +
    + {% for error in form.episodies_number.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} +
+
+ + {{ form.year }} + * formato: YYYY-MM-DD + {% if form.year.errors %} +
    + {% for error in form.year.errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} +
diff --git a/tvseries/core/views.py b/tvseries/core/views.py index 7347dcd..ecfcfa5 100644 --- a/tvseries/core/views.py +++ b/tvseries/core/views.py @@ -1,11 +1,12 @@ import os from random import choice -from flask import render_template, url_for, redirect, request +from flask import render_template, url_for, redirect from tvseries.ext import db from tvseries.core import core_blueprint from tvseries.core.models import TVSerie +from tvseries.core.forms import TVSerieForm @core_blueprint.route('') @@ -20,16 +21,17 @@ def home(name=None): @core_blueprint.route('add', methods=['GET', 'POST']) def add(): - if request.method == 'POST': - name = request.form.to_dict().get('serie-name') - description = request.form.to_dict().get('serie-description') - author = request.form.to_dict().get('serie-author') - episodies_number = request.form.to_dict().get('serie-episodes_number') - + form = TVSerieForm() + if form.validate_on_submit(): + name = form.name.data + description = form.description.data + author = form.author.data + episodies_number = form.episodies_number.data + year = form.year.data serie = TVSerie(name=name, description=description, author=author, - episodies_number=episodies_number) + episodies_number=episodies_number, year=year) db.session.add(serie) db.session.commit() return redirect('/') - return render_template('add.html') + return render_template('add.html', form=form) diff --git a/tvseries/tests/test_core.py b/tvseries/tests/test_core.py index 8f136a9..3f1a1df 100644 --- a/tvseries/tests/test_core.py +++ b/tvseries/tests/test_core.py @@ -26,23 +26,37 @@ def test_get_add_status_code(self): def test_get_add_content(self): response = self.client.get("/add") expected = ( - 'name="serie-name" id="id_serie-name"', - 'name="serie-description" id="id_serie-description"', - 'name="serie-author" id="id_serie-author"', - 'name="serie-episodies_number" id="id_serie-episodies_number"', + '', + '', + '', + '', + '', ) for field in expected: assert field in response.data.decode('utf-8') def test_post_add(self, db): response = self.client.post("/add", data={ - "serie-name": "Game of Thrones", - "serie-author": "George R.R. Martin", - "serie-description": "Teste", + "name": "Game of Thrones", + "description": "Teste", + "author": "George R.R. Martin", + "episodies_number": "60", + "year": date(2011, 1, 1) }) result = TVSerie.query.filter(TVSerie.name == 'Game of Thrones') assert response.status_code == 302 and result.count() == 1 + def test_post_add_with_invalid_data(self, db): + response = self.client.post("/add", data={ + "name": "Game of Thrones", + "description": "Teste", + "author": "George R.R. Martin", + "episodies_number": "60", + "year": "aaaaaaa" + }) + result = TVSerie.query.filter(TVSerie.name == 'Game of Thrones') + assert response.status_code == 200 and result.count() == 0 + def test_navbar(self, db): response = self.client.get("/") assert ('