From dc3d493d238e57b307a70de7cf45636550dcdad3 Mon Sep 17 00:00:00 2001 From: viniciusarcanjo Date: Sat, 31 Oct 2015 19:59:25 -0200 Subject: [PATCH 1/3] Restruturacao completa para Django e inicio de modelagem e testes para o django app carroceiro --- .gitignore | 4 ++ README.md | 57 ++++++++++++++++- app/README.md | 11 ---- app/__init__.py | 25 -------- app/app.py | 3 - app/auth.py | 0 app/catadores/__init__.py | 4 -- app/catadores/controllers.py | 0 app/catadores/models.py | 0 app/catadores/views.py | 0 app/config.py | 87 -------------------------- app/databases.py | 15 ----- app/models.py | 31 --------- app/routes.py | 23 ------- app/users/__init__.py | 0 app/users/controllers.py | 0 app/users/models.py | 0 app/users/routes.py | 0 app/users/views.py | 0 {app => app_site}/.gitignore | 0 data/long_lat_pimp_carroceiros_app.sql | 17 +++++ data/long_lat_pimp_catadores_app.csv | 18 ------ data/long_lat_pimp_catadores_app.sql | 17 ----- docs/routes.md | 33 +++++++--- requirements.txt | 22 +++---- scripts/curl.py | 10 --- scripts/echoserver.py | 26 -------- scripts/load_catadores.sh | 7 +-- 28 files changed, 109 insertions(+), 301 deletions(-) delete mode 100644 app/README.md delete mode 100644 app/__init__.py delete mode 100644 app/app.py delete mode 100644 app/auth.py delete mode 100644 app/catadores/__init__.py delete mode 100644 app/catadores/controllers.py delete mode 100644 app/catadores/models.py delete mode 100644 app/catadores/views.py delete mode 100644 app/config.py delete mode 100644 app/databases.py delete mode 100644 app/models.py delete mode 100644 app/routes.py delete mode 100644 app/users/__init__.py delete mode 100644 app/users/controllers.py delete mode 100644 app/users/models.py delete mode 100644 app/users/routes.py delete mode 100644 app/users/views.py rename {app => app_site}/.gitignore (100%) create mode 100644 data/long_lat_pimp_carroceiros_app.sql delete mode 100644 data/long_lat_pimp_catadores_app.csv delete mode 100644 data/long_lat_pimp_catadores_app.sql delete mode 100644 scripts/curl.py delete mode 100644 scripts/echoserver.py diff --git a/.gitignore b/.gitignore index 9a917d2..cd2e302 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,7 @@ target/ # Virtualenv venv/ env/ + +# cache results from py.test +integration_test/.cache +.cache diff --git a/README.md b/README.md index f5f4236..d1b92f0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,55 @@ -# pimpapp-api +=============================== +Pre requisitos para rodar o app +=============================== + +-> Ativar virtualenv + +source venv/bin/activate + +-> Instalar todos as python libraries + +pip install -r requirements.txt + +================= +Como rodar o app: +================= + +================================================================================================== +Estes dois passos a seguir somente deverao ser executado uma vez ou quando o models.py for alterado +================================================================================================== + +-> Realizar makemigrations (se necessario futuramente alterar o models.py) e migrate para criar as databases atraves do django +-> *** Posteriormente, caso necessario visualizar o sql gerado pelo django, basta realizar "python manage.py sqlall carroceiro" + +python manage.py migrate + +-> Carregar dados iniciais no db atraves do script load_catadores.sh + +cd scripts +sh load_catadores.sh + +-> Inicializar o server + +python manage.py runserver + +================================== +Como rodar os testes de integracao: +================================== + +py.test integration_tests/tests.py + +Obs: Como sao testes de integracao, eh necessario que a database esteja existente e funcional (django migrate stuff) + +================================================================================================================== +Como Recriar todas as databases do django (caso necessario algum debug ou destruir as databases por algum motivo): +================================================================================================================== + +python manage.py reset_db + +-> Posteriormente utilizar + +python manage.py migrate + +-> Executar novamente o script load_catadores.sh para inicializar data no db. + -[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PimpAPP/pimpapp-api?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -API REST utilizada no pimp diff --git a/app/README.md b/app/README.md deleted file mode 100644 index 4d966b3..0000000 --- a/app/README.md +++ /dev/null @@ -1,11 +0,0 @@ -Como rodar: -=========== - -* Primeiro executar o arquivo ``app/databases.py`` -Isso irá criar o esquema da base de dados - -* Rodar ``scripts/load_catadores.sh`` -Isso irá carregar uma pequena base de catadores - -* Rodar ``app/routes.py`` -Isso irá subir o o servidor de desenvolvimento diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100644 index 8b7d09a..0000000 --- a/app/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -from flask import Flask -from app import config - - -def create_app(config_name): - """TODO: Docstring for create_app. - - :config_name: TODO - :returns: TODO - - """ - - # start Flask app and load config - app = Flask(__name__) - config.config[config_name](app) - - #register all blueprints - - #init extensions - - #load all routes - - #auth token - - return app diff --git a/app/app.py b/app/app.py deleted file mode 100644 index d7562aa..0000000 --- a/app/app.py +++ /dev/null @@ -1,3 +0,0 @@ -from flask import Flask - -app = Flask(__name__) diff --git a/app/auth.py b/app/auth.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/catadores/__init__.py b/app/catadores/__init__.py deleted file mode 100644 index ff2bd36..0000000 --- a/app/catadores/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from flask import Blueprint - - - diff --git a/app/catadores/controllers.py b/app/catadores/controllers.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/catadores/models.py b/app/catadores/models.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/catadores/views.py b/app/catadores/views.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/config.py b/app/config.py deleted file mode 100644 index 1a5a35f..0000000 --- a/app/config.py +++ /dev/null @@ -1,87 +0,0 @@ -import os - - -class Config(): - - """TODO: Docstring for Config. """ - - config_dict = { - 'SECRET_KEY': 'AReallySecretKey', - 'JWT_AUTH_URL_RULE': '/api/auth' - } - - def init_app(self, app): - """TODO: Docstring for init_app. - - :app: TODO - :config_dict: TODO - :returns: TODO - - """ - app.config.update(**self.config_dict) - - -class DevelopmentConfig(Config): - - """TODO: Docstring for DevelopmentConfig. """ - - DB_NAME = 'dev.db' - DB_PATH = os.path.join(Config.PROJECT_ROOT, DB_NAME) - SQLALCHEMY_DATABASE_URI = 'sqlite:///{0}'.format(DB_PATH) - - def __init__(self, app=None): - """TODO: Docstring for __init__. - - :app: TODO - :returns: TODO - - """ - if app: - self.config_dict.update({ - 'DEBUG': True, - 'DB_NAME': 'dev.db', - 'DB_PATH': os.path.join(Config.PROJECT_ROOT, DB_NAME), - 'SQLALCHEMY_DATABASE_URI': 'sqlite:///{0}'.format(DB_PATH), - }) - self.init_app(app) - - -class TestingConfig(Config): - - """Docstring for TestingConfig. """ - - def __init__(self, app=None): - """TODO: Docstring for __init__. - - :arg1: TODO - - :app: TODO - :returns: TODO - - """ - if app: - self.init_app(app) - - -class ProductionConfig(Config): - - """Docstring for ProductionConfig. """ - - def __init__(self, app=None): - """TODO: Docstring for __init__. - - :arg1: TODO - - :app: TODO - :returns: TODO - - """ - if app: - self.init_app(app) - -config = { - 'development': DevelopmentConfig, - 'testing': TestingConfig, - 'production': ProductionConfig, - 'default': DevelopmentConfig -} diff --git a/app/databases.py b/app/databases.py deleted file mode 100644 index 7edbd99..0000000 --- a/app/databases.py +++ /dev/null @@ -1,15 +0,0 @@ -from models import Base, Catador -from flask_sqlalchemy import SQLAlchemy - -from app import app - -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3' -db = SQLAlchemy(app) - -def init_db(): - Base.metadata.drop_all(bind=db.engine) - Base.metadata.create_all(bind=db.engine) - db.session.commit() - -if __name__ == '__main__': - init_db() diff --git a/app/models.py b/app/models.py deleted file mode 100644 index 96a8506..0000000 --- a/app/models.py +++ /dev/null @@ -1,31 +0,0 @@ -import json - -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy import Column, Integer, String, Float - -Base = declarative_base() - -class Catador(Base): - __tablename__ = 'catador' - id = Column(Integer, primary_key=True) - name = Column(String(50), unique=False) - phone = Column(String(20), unique=False) - address = Column(String(120), unique=False) - latitude = Column(Float(), unique=False) - longitude = Column(Float(), unique=False) - - def __init__(self, name=None): - self.name = name - - def __repr__(self): - return '' % (self.name) - - def to_JSON(self): - return json.dumps({ - "id": self.id, - "name": self.name, - "phone": self.phone, - "address": self.address, - "latitude": self.latitude, - "longitude": self.longitude, - }, indent=4) diff --git a/app/routes.py b/app/routes.py deleted file mode 100644 index 28a1850..0000000 --- a/app/routes.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask import Response -from flask_sqlalchemy import SQLAlchemy - -from app import app -from databases import db -from models import Base, Catador - - -@app.route('/') -def index(): - catadores = db.session.query(Catador).all() - return u"
".join([u"{0}".format(c.name) for c in catadores]) - - -@app.route('/catador/') -def get_catador(id): - catador = db.session.query(Catador).get(id) - response = Response(catador.to_JSON(), - status=200, mimetype="application/json") - return response - -if __name__ == '__main__': - app.run('127.0.0.1', 5000, debug=True) diff --git a/app/users/__init__.py b/app/users/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/users/controllers.py b/app/users/controllers.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/users/models.py b/app/users/models.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/users/routes.py b/app/users/routes.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/users/views.py b/app/users/views.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/.gitignore b/app_site/.gitignore similarity index 100% rename from app/.gitignore rename to app_site/.gitignore diff --git a/data/long_lat_pimp_carroceiros_app.sql b/data/long_lat_pimp_carroceiros_app.sql new file mode 100644 index 0000000..8040fb5 --- /dev/null +++ b/data/long_lat_pimp_carroceiros_app.sql @@ -0,0 +1,17 @@ +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Rafael dos Santos", "982416387", "Rua Dos Gusmões, 500", -23.5374089, -46.6399287); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Rodrigue Lucena", "984357774","Av Liberdade 163", -23.5544961, -46.6354377); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Gabriel dos Santos", "954861273", "Rua Ferreira de Araújo", -23.5577321, -46.6973732); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Denilson", "954167784", "Rua Cardeal Arco Verde 1000", -23.5577372, -46.6817867); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Jorge Natalino", "943270892", "Rua Rodesia 220", -23.5513181, -46.6907592); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Nego", "967847079","Rua Belmiro Braga n 216", -23.55757172, -46.68607322); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Fábio", "988412088", "Rua Harmonia 71", -23.5571661, -46.6867196); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Buiu", "989083725", "Rua Pedroso de Moraes 1280", -23.5599579, -46.693902); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Marco Viana dos Santos","975004604","Rua Arthur de Azevedo n 550", -23.5600974, -46.6774287); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Biro-Biro", "977399129", "Av Faria Lima 2200", -23.5755786, -46.6876801); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Sergio Bispo", "962270116", "Rua Glicerio 123", -23.5529011, -46.6276388); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Fernando Miguel", "948867162", "Metrô Armênia", -23.525545, -46.629317); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Marquinhos", "957207459", "Av Rebouças 3000", -23.5696463, -46.6882664); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Priscila", "964579284", "Av. Roberto Marinho 1550", -23.6186647, -46.6832331); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Jose Teixeira Dantas", "972059149", "R. Barão de Paranapiacaba", -23.5494343, -46.6338535); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Denilson", "954167784", "Rua Inacio Pereira da Rocha n 25", -23.5586191, -46.6872522); +INSERT INTO carroceiro_carroceiro (name, phone, address, latitude, longitude) VALUES ("Jose Parque do Gato", "984678922", "Rua Newtom Prado n 500", -23.5226943, -46.6405354); diff --git a/data/long_lat_pimp_catadores_app.csv b/data/long_lat_pimp_catadores_app.csv deleted file mode 100644 index e4f06a6..0000000 --- a/data/long_lat_pimp_catadores_app.csv +++ /dev/null @@ -1,18 +0,0 @@ -Nome Completo,Telefone,Endereço,latitude,longitude -Rafael dos Santos,98241.6387,"Rua Dos Gusmões, 500",-23.5374089,-46.6399287 -Rodrigue Lucena,98435.7774,"Av Liberdade, 163",-23.5544961,-46.6354377 -Gabriel dos Santos,954861273,"Rua Ferreira de Araújo",-23.5577321,-46.6973732 -Denilson,954167784,"Rua Cardeal Arco Verde 1000",-23.5577372,-46.6817867 -Jorge Natalino,94327-0892,"Rua Rodesia 220",-23.5513181,-46.6907592 -Nego,96784-7079,"Rua Belmiro Braga n 216",23.55757172,-46.68607322 -Fábio,98841-2088,"Rua Harmonia 71",-23.5571661,-46.6867196 -Buiu,98908-3725,"Rua Pedroso de Moraes 1280",-23.5599579,-46.693902 -Marco Viana dos Santos,975004604,"Rua Arthur de Azevedo n 550",-23.5600974,-46.6774287 -Biro-Biro,977399129,"Av Faria Lima 2200",-23.5755786,-46.6876801 -Sergio Bispo,962270116,"Rua Glicerio 123",-23.5529011,-46.6276388 -Fernando Miguel,948867162,"Metrô Armênia",-23.525545,-46.629317 -Marquinhos,95720-7459,"Av Rebouças 3000",-23.5696463,-46.6882664 -Priscila ,964579284,"Av. Roberto Marinho 1550",-23.6186647,-46.6832331 -Jose Teixeira Dantas,97205-9149,"R. Barão de Paranapiacaba",-23.5494343,-46.6338535 -Denilson,954167784,"Rua Inacio Pereira da Rocha n 25",-23.5586191,-46.6872522 -Jose Parque do Gato,984678922,"Rua Newtom Prado n 500",-23.5226943,-46.6405354 diff --git a/data/long_lat_pimp_catadores_app.sql b/data/long_lat_pimp_catadores_app.sql deleted file mode 100644 index 2ecaeeb..0000000 --- a/data/long_lat_pimp_catadores_app.sql +++ /dev/null @@ -1,17 +0,0 @@ -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Rafael dos Santos", "98241.6387", "Rua Dos Gusmões, 500", -23.5374089, -46.6399287); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Rodrigue Lucena", "98435.7774","Av Liberdade 163", -23.5544961, -46.6354377); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Gabriel dos Santos", "954861273", "Rua Ferreira de Araújo", -23.5577321, -46.6973732); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Denilson", "954167784", "Rua Cardeal Arco Verde 1000", -23.5577372, -46.6817867); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Jorge Natalino", "94327-0892", "Rua Rodesia 220", -23.5513181, -46.6907592); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Nego", "96784-7079","Rua Belmiro Braga n 216", -23.55757172, -46.68607322); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Fábio", "98841-2088", "Rua Harmonia 71", -23.5571661, -46.6867196); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Buiu", "98908-3725", "Rua Pedroso de Moraes 1280", -23.5599579, -46.693902); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Marco Viana dos Santos","975004604","Rua Arthur de Azevedo n 550", -23.5600974, -46.6774287); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Biro-Biro", "977399129", "Av Faria Lima 2200", -23.5755786, -46.6876801); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Sergio Bispo", "962270116", "Rua Glicerio 123", -23.5529011, -46.6276388); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Fernando Miguel", "948867162", "Metrô Armênia", -23.525545, -46.629317); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Marquinhos", "95720-7459", "Av Rebouças 3000", -23.5696463, -46.6882664); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Priscila", "964579284", "Av. Roberto Marinho 1550", -23.6186647, -46.6832331); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Jose Teixeira Dantas", "97205-9149", "R. Barão de Paranapiacaba", -23.5494343, -46.6338535); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Denilson", "954167784", "Rua Inacio Pereira da Rocha n 25", -23.5586191, -46.6872522); -INSERT INTO catador (name, phone, address, latitude, longitude) VALUES ("Jose Parque do Gato", "984678922", "Rua Newtom Prado n 500", -23.5226943, -46.6405354); diff --git a/docs/routes.md b/docs/routes.md index 3929a7c..8ca8e35 100644 --- a/docs/routes.md +++ b/docs/routes.md @@ -1,8 +1,29 @@ _Ideias iniciais para rotas. Passar para wiki depois..._ -### Catadores -#### /catadores +->>>>> CARROCEIRO <<<<<<- + +#### /carroceiro/id/ + +Interface para o Profile dos Catadores + +* __GET__ -> Detalhes de um carroceiro especifico. +* __PUT__ -> Atualiza os dados de um carroceiro. +* __DELETE__ -> Apagar um carroceiro. + + +#### /carroceiro/ + +Lista de carroceiros, para listar todos ou incluir novos. + +* __GET__ -> Detalhes de um carroceiro especifico. +* __POST__ -> Adiciona um novo carroceiro. + + +->>>> TODO <<<<- (Discutir como vai ficar or argumentos e CRUD) + +### Carroceiros filtros + Interface de filtros. * __GET__ -> Lista com todos os catadores * /catadores/?material="slug_material" @@ -11,14 +32,6 @@ Interface de filtros. * /catadores/?google_maps_q="google_maps_q" * /catadores/?actor="actor" - -#### /catador -Interface para o Profile dos Catadores -* __GET__ -> Detalhes de um catador especifico. -* __POST__ ou __PUT__ -> Atualiza os dados de um catador. -* __DELETE__ -> Apagar um catador. - - ### Material #### /materials diff --git a/requirements.txt b/requirements.txt index 9d6a08a..a60e161 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,8 @@ -aniso8601==0.92 -Flask==0.10.1 -Flask-JWT==0.2.0 -Flask-RESTful==0.3.1 -Flask-SQLAlchemy==2.0 -geolocation-python==0.2.0 -itsdangerous==0.24 -Jinja2==2.7.3 -MarkupSafe==0.23 -pytz==2014.10 -requests==2.5.1 -six==1.9.0 -SQLAlchemy==0.9.8 -Werkzeug==0.9.6 +Django==1.8.5 +django-extensions==1.5.7 +djangorestframework==3.3.0 +py==1.4.30 +pytest==2.8.2 +requests==2.8.1 +six==1.10.0 +test-pkg==0.0 diff --git a/scripts/curl.py b/scripts/curl.py deleted file mode 100644 index 98fc326..0000000 --- a/scripts/curl.py +++ /dev/null @@ -1,10 +0,0 @@ -import os - -# TODO read from sys.args -METHOD = 'POST' -FILE = 'test.json' -HOST = '127.0.0.1' -PORT = '21012' - -os.execv('/usr/bin/curl', ['usr/bin/curl', '-H', 'Content-Type: application/json', '-X' , - METHOD, '-d', '@'+FILE, '%s:%s' % (HOST, PORT)]) diff --git a/scripts/echoserver.py b/scripts/echoserver.py deleted file mode 100644 index be36492..0000000 --- a/scripts/echoserver.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python - -import socket - -""" -A simple echo server -""" - -host = '127.0.0.1' -#host = '192.168.0.30' -port = 21012 -backlog = 5 -size = 1024 - -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.bind((host,port)) -s.listen(backlog) - -print 'Echo running on %s:%d' % (host, port) -while True: - client, address = s.accept() - data = client.recv(size) - if data: - #print data - client.send(data) - client.close() diff --git a/scripts/load_catadores.sh b/scripts/load_catadores.sh index 59c1ced..ba81873 100755 --- a/scripts/load_catadores.sh +++ b/scripts/load_catadores.sh @@ -1,7 +1,6 @@ #!/bin/bash -set -e +cat ../data/long_lat_pimp_carroceiros_app.sql | sqlite3 ../app_site/db.sqlite3 -sqlite3 ../app/db.sqlite3 "SELECT * FROM sqlite_master WHERE type='table';" -cat ../data/long_lat_pimp_catadores_app.sql | sqlite3 ../app/db.sqlite3 -sqlite3 ../app/db.sqlite3 "SELECT * FROM catador;" +# Para visualizar atraves de uma GUI o db, eh possivel utilizar o sqlitebrowser passando o db.sqlite3 como argumento +# sqlitebrowser db.sqlite3 From 9656253c4ce50b1d17e82cf95b6178a1c664ff65 Mon Sep 17 00:00:00 2001 From: viniciusarcanjo Date: Sat, 31 Oct 2015 20:02:42 -0200 Subject: [PATCH 2/3] adicionado arquivos do app_site que tinham ficado de fora --- app_site/__init__.py | 1 + app_site/app_site/__init__.py | 0 app_site/app_site/settings.py | 105 +++++++++++++++++++++++++++++ app_site/app_site/urls.py | 22 ++++++ app_site/app_site/wsgi.py | 16 +++++ app_site/carroceiro/__init__.py | 0 app_site/carroceiro/admin.py | 3 + app_site/carroceiro/models.py | 36 ++++++++++ app_site/carroceiro/serializers.py | 11 +++ app_site/carroceiro/urls.py | 16 +++++ app_site/carroceiro/views.py | 73 ++++++++++++++++++++ app_site/manage.py | 10 +++ 12 files changed, 293 insertions(+) create mode 100644 app_site/__init__.py create mode 100644 app_site/app_site/__init__.py create mode 100644 app_site/app_site/settings.py create mode 100644 app_site/app_site/urls.py create mode 100644 app_site/app_site/wsgi.py create mode 100644 app_site/carroceiro/__init__.py create mode 100644 app_site/carroceiro/admin.py create mode 100644 app_site/carroceiro/models.py create mode 100644 app_site/carroceiro/serializers.py create mode 100644 app_site/carroceiro/urls.py create mode 100644 app_site/carroceiro/views.py create mode 100755 app_site/manage.py diff --git a/app_site/__init__.py b/app_site/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app_site/__init__.py @@ -0,0 +1 @@ + diff --git a/app_site/app_site/__init__.py b/app_site/app_site/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app_site/app_site/settings.py b/app_site/app_site/settings.py new file mode 100644 index 0000000..aa86874 --- /dev/null +++ b/app_site/app_site/settings.py @@ -0,0 +1,105 @@ +""" +Django settings for app_site project. + +Generated by 'django-admin startproject' using Django 1.8.5. + +For more information on this file, see +https://docs.djangoproject.com/en/1.8/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/1.8/ref/settings/ +""" + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +import os + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'yvmahv(pa39%+5fs8%jxg79ejm^ui13m#fma3rf0kd7#r-wc9k' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'rest_framework', + 'django_extensions', + 'carroceiro', +) + +MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.security.SecurityMiddleware', +) + +ROOT_URLCONF = 'app_site.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'app_site.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/1.8/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Internationalization +# https://docs.djangoproject.com/en/1.8/topics/i18n/ + +LANGUAGE_CODE = 'pt-br' + +TIME_ZONE = 'America/Sao_Paulo' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.8/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/app_site/app_site/urls.py b/app_site/app_site/urls.py new file mode 100644 index 0000000..278fd5d --- /dev/null +++ b/app_site/app_site/urls.py @@ -0,0 +1,22 @@ +"""app_site URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.8/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Add an import: from blog import urls as blog_urls + 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) +""" +from django.conf.urls import include, url +from django.contrib import admin + +urlpatterns = [ + url(r'^admin/', include(admin.site.urls)), + url(r'^carroceiro/', include('carroceiro.urls')), +] diff --git a/app_site/app_site/wsgi.py b/app_site/app_site/wsgi.py new file mode 100644 index 0000000..7a1e1aa --- /dev/null +++ b/app_site/app_site/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for app_site project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app_site.settings") + +application = get_wsgi_application() diff --git a/app_site/carroceiro/__init__.py b/app_site/carroceiro/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app_site/carroceiro/admin.py b/app_site/carroceiro/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/app_site/carroceiro/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/app_site/carroceiro/models.py b/app_site/carroceiro/models.py new file mode 100644 index 0000000..37c31b7 --- /dev/null +++ b/app_site/carroceiro/models.py @@ -0,0 +1,36 @@ +from django.db import models +from django.core.validators import RegexValidator + +class CarroceiroAlreadyExistsException(Exception): + pass + +class Carroceiro(models.Model): + + """ + Class used for modeling a instance of Carroceiro in our DB. + by default, this table will be addressed as carroceiro_carroceiro + """ + name = models.CharField(max_length=50, default='') + phone = models.CharField(max_length=15, validators=[RegexValidator(regex=r'^\d{8,15}$', + message='Phone number must have at least 8 digits and/or up to 15 digits.')], default='00000000') + address = models.CharField(max_length=120, default='') + latitude = models.FloatField(default=0.0) + longitude = models.FloatField(default=0.0) + + # This method was overwriten to make sure that every time a phone is stored it belongs to the same person. + # And to avoid that the same person is registred twich on the same adress, latitude and longitude. + def save(self, force_insert=False, force_update=False, using=None, + update_fields=None): + carroceiro_list = Carroceiro.objects.filter(phone=self.phone) + for c in carroceiro_list: + if not ((c.name == self.name) and (c.phone == self.phone)): + raise CarroceiroAlreadyExistsException("This phone belong to another carroceiro") + for c in carroceiro_list: + if (c.longitude == self.longitude) and (c.latitude == self.latitude) and (c.adress == self.address): + raise CarroceiroAlreadyExistsException("This carroceiro is already in our database, " + "you can't register the same person on the same adress twice") + super(Carroceiro, self).save() + + + def __str__(self): + return self.name diff --git a/app_site/carroceiro/serializers.py b/app_site/carroceiro/serializers.py new file mode 100644 index 0000000..d125156 --- /dev/null +++ b/app_site/carroceiro/serializers.py @@ -0,0 +1,11 @@ +from django.contrib.auth.models import User +from rest_framework import serializers +from .models import Carroceiro + +class CarroceiroSerializer(serializers.ModelSerializer): + """ + Class used for serialization Carroceiro into JSON + """ + class Meta: + model = Carroceiro + fields = ('id', 'name', 'phone', 'address', 'latitude', 'longitude') diff --git a/app_site/carroceiro/urls.py b/app_site/carroceiro/urls.py new file mode 100644 index 0000000..578ccc4 --- /dev/null +++ b/app_site/carroceiro/urls.py @@ -0,0 +1,16 @@ +from django.conf.urls import url + +from . import views + +""" +/carroceiro/ is the URL path from the root "app_site.urls.py" point of view to carroceiro.urls.py. +""" + +urlpatterns = [ + # ex: /carroceiro/, will list all carroceiros + url(r'^$', views.CarroceirosList.as_view(), name='carroceiro-list'), + # ex: /carroceiro// + url(r'^(?P[0-9]+)/$', views.CarroceiroDetail.as_view(), name='carroceiro-detail'), + # ex: /carroceiro/phone// + url(r'^phone/(?P\d{8,15})/$', views.CarroceiroFindByPhone.as_view(), name='carroceiro-findbyphone'), +] \ No newline at end of file diff --git a/app_site/carroceiro/views.py b/app_site/carroceiro/views.py new file mode 100644 index 0000000..a1ddeb4 --- /dev/null +++ b/app_site/carroceiro/views.py @@ -0,0 +1,73 @@ +from .models import Carroceiro +from .models import CarroceiroAlreadyExistsException +from .serializers import CarroceiroSerializer +from rest_framework.views import APIView +from rest_framework.response import Response +from django.http import Http404 +from rest_framework import status + + +class CarroceirosList(APIView): + """ + List all Carroceiros and/or Create a new Carroceiro. + """ + def get(self, request, format=None): + carroceiros = Carroceiro.objects.all() + serializer = CarroceiroSerializer(carroceiros, many=True) + return Response(serializer.data) + + def post(self, request, format=None): + serializer = CarroceiroSerializer(data=request.data) + # regex validation first + if serializer.is_valid(): + try: + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + except CarroceiroAlreadyExistsException: + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +class CarroceiroFindByPhone(APIView): + """ + List all Carroceiros given their cellphone, in our database cellphone is not unique but behaves like a id. + It's assumed that a Carroceiro can have multiple addresses, hence one cellphone would have multiple entries (all of them MUST belong to the same person though) + """ + def get(self, request, phone, format=None): + try: + carroceiro_list = Carroceiro.objects.filter(phone=phone) + carroceiro_list_serializer = CarroceiroSerializer(carroceiro_list, many=True) + return Response(carroceiro_list_serializer.data) + except Carroceiro.DoesNotExist: + raise Http404 + +class CarroceiroDetail(APIView): + """ + Update , Retrieve and Delete a instance of Carroceiro given their id. + """ + def get(self, request, id, format=None): + try: + carroceiro = Carroceiro.objects.get(id=id) + carroceiro = CarroceiroSerializer(carroceiro) + return Response(carroceiro.data) + except Carroceiro.DoesNotExist: + raise Http404 + + def delete(self, request, id, format=None): + try: + carroceiro = Carroceiro.objects.get(id=id) + carroceiro.delete() + return Response(status=status.HTTP_204_NO_CONTENT) + except Carroceiro.DoesNotExist: + raise Http404 + + def put(self, request, id, format=None): + carroceiro = Carroceiro.objects.get(id=id) + serializer = CarroceiroSerializer(carroceiro, data=request.data) + if serializer.is_valid(): + try: + serializer.save() + return Response(serializer.data) + except CarroceiroAlreadyExistsException: + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + diff --git a/app_site/manage.py b/app_site/manage.py new file mode 100755 index 0000000..91bd39c --- /dev/null +++ b/app_site/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app_site.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) From cd723ce08a829de6a856a8a6f689b38912d9f32f Mon Sep 17 00:00:00 2001 From: viniciusarcanjo Date: Sat, 31 Oct 2015 20:03:46 -0200 Subject: [PATCH 3/3] adicionado arquivos de integration_tests --- integration_tests/curl_shell_cmds.md | 24 ++++ integration_tests/tests.py | 180 +++++++++++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 integration_tests/curl_shell_cmds.md create mode 100644 integration_tests/tests.py diff --git a/integration_tests/curl_shell_cmds.md b/integration_tests/curl_shell_cmds.md new file mode 100644 index 0000000..85f2933 --- /dev/null +++ b/integration_tests/curl_shell_cmds.md @@ -0,0 +1,24 @@ + +http://wiki.servicenow.com/index.php?title=Table_API_Curl_Examples#gsc.tab=0 + +# curl get test + +# Some curl commands to test the API manually on shell. + +curl -i -H "Accept: application/json" -H "Content-Type: application/json" http://127.0.0.1:8000/carroceiro/ +curl -i -H "Accept: application/json" -H "Content-Type: application/json" http://127.0.0.1:8000/carroceiro/1 + +# curl post test + +curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"name":"test","phone":"11111111111","address":"Av Independencia, 500","latitude":-11.111111,"longitude":-22.222222}' http://127.0.0.1:8000/carroceiro/ + +# curl put test + +curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X PUT -d '{"name":"test","phone":"22222222222","address":"Av Independencia, 500","latitude":-11.111111,"longitude":-22.222222}' http://127.0.0.1:8000/carroceiro/20/ + +# curl delete test + +curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X DELETE -d '{"name":"test","phone":"22222222222","address":"Av Independencia, 500","latitude":-11.111111,"longitude":-22.222222}' http://127.0.0.1:8000/carroceiro/20/ + + + diff --git a/integration_tests/tests.py b/integration_tests/tests.py new file mode 100644 index 0000000..711248b --- /dev/null +++ b/integration_tests/tests.py @@ -0,0 +1,180 @@ +import requests +import random +import string + +#################################################### +# Global vars that will be used for testing purposes +#################################################### + +valid_carroceiro_1 = {"name": "carroceiro_test", "phone": "999111111", + "address": "Av test, 9999", "latitude": -11.11, "longitude": -22.22} + +# same carroceiro, including phone, but different address for example, this would be his house addresss +valid_carroceiro_2 = {"name": "carroceiro_test", "phone": "999111111", + "address": "Av test, 1111", "latitude": -22.22, "longitude": -22.11} + +# carroceiro's id(s) +ids = [] + +class TestCarroceirosListViews(): + """ + Class designed for testing the CarroceirosList class, which belongs to carroceiro.views + """ + + + def test_get(self): + + try: + r = requests.get('http://localhost:8000/carroceiro/') + assert r.status_code == 200 + assert not r.json() == [], "The carroceiro_carroceiro table is empty! \ + You're supposed to run these tests with some entries in the database" + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + + def test_post_valid_carroceiro(self): + + try: + r = requests.post('http://localhost:8000/carroceiro/', json=valid_carroceiro_1) + assert r.status_code == 201 + + r = requests.post('http://localhost:8000/carroceiro/', json=valid_carroceiro_2) + assert r.status_code == 201 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + + def test_post_invalid_carroceiro(self): + + try: + # post same carroceiro again who as used on test_post_valid_carroceiro + data = {"name": "carroceiro_test", "phone": "999111111", + "address": "Av test, 9999", "latitude": -11.11, "longitude": -22.22} + r = requests.post('http://localhost:8000/carroceiro/', json=data) + assert r.status_code == 400 or r.status_code == 500 + + # invalid phone with less than 8 digits + data = {"name": "carroceiro_test", "phone": "8411122", + "address": "Av test, 9999", "latitude": -11.11, "longitude": -22.22} + r = requests.post('http://localhost:8000/carroceiro/', json=data) + assert r.status_code == 400 or r.status_code == 500 + + # changing the name, thiw will mismatch because this phone already exists and BELONGS to "carroceiro_test" + data['name'] = 'carroceiro_test2' + r = requests.post('http://localhost:8000/carroceiro/', json=data) + assert r.status_code == 400 or r.status_code == 500 + + # invalid phone with more than 15 digits + data['phone'] = "9991111111111111" + r = requests.post('http://localhost:8000/carroceiro/', json=data) + assert r.status_code == 400 or r.status_code == 500 + + # invalid phone with letters + data['phone'] = "asdf" + r = requests.post('http://localhost:8000/carroceiro/', json=data) + assert r.status_code == 400 or r.status_code == 500 + + # a null string attribute, all varchar entries in the DB can't be null + data['name'] = '' + r = requests.post('http://localhost:8000/carroceiro/', json=data) + assert r.status_code == 400 or r.status_code == 500 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + +class TestCarroceiroFindByPhone(): + """ + Class designed for testing the CarroceiroFindByPhone class, which belongs to carroceiro.views + """ + + def test_get(self): + try: + r = requests.get('http://localhost:8000/carroceiro/phone/{0}/'.format(valid_carroceiro_1['phone'])) + assert r.status_code == 200 + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + +class TestCarroceiroDetail(): + """ + Class designed for testing the CarroceiroDetail class, which belongs to carroceiro.views + """ + + def test_valid_get(self): + + try: + # Before we test we need their ids which can be obtained with findbyphone view. + r = requests.get('http://localhost:8000/carroceiro/phone/{0}/'.format(valid_carroceiro_1['phone'])) + assert r.status_code == 200 + my_data = r.json() + + for my_dict in my_data: + # ids is a global var + ids.append(my_dict['id']) # saving on this list for other next tests like put and delete. + r = requests.get('http://localhost:8000/carroceiro/{0}/'.format(my_dict['id'])) + assert r.status_code == 200 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + def test_invalid_get(self): + + try: + r = requests.get('http://localhost:8000/carroceiro/99999999999/') + assert r.status_code == 404 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + def test_put(self): + + try: + # since one carroceiro can have multiple ids.. + for id in ids: + # this put will change their names to a random name and their phone. + # I have to change their phone too because you can't have two different carroceiro.names who's got same phone number + valid_carroceiro_1['name'] = ''.join(random.sample(string.ascii_lowercase, 10)) + valid_carroceiro_1['phone'] = str(int(valid_carroceiro_1['phone']) + 100) + r = requests.put('http://localhost:8000/carroceiro/{0}/'.format(id), json=valid_carroceiro_1) + assert r.status_code == 200 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + def test_invalid_put(self): + + try: + r = requests.put('http://localhost:8000/carroceiro/9999999999/', json=valid_carroceiro_1) + assert r.status_code == 400 or r.status_code == 500 + + # testing a valid id, but wrong json data (null name) + invalid_carroceiro = valid_carroceiro_1 + invalid_carroceiro['name'] = '' + + r = requests.put('http://localhost:8000/carroceiro/{0}/'.format(ids[0]), json=invalid_carroceiro) + assert r.status_code == 400 or r.status_code == 500 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + def test_delete(self): + + try: + # since one carroceiro can have multiple ids.. + for id in ids: + r = requests.delete('http://localhost:8000/carroceiro/{0}/'.format(id)) + assert r.status_code == 204 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" + + def test_invalid_delete(self): + + try: + r = requests.delete('http://localhost:8000/carroceiro/888888888888/') + assert r.status_code == 404 or r.status_code == 500 + + except ConnectionError: + assert False, "It couldn't connect to the database, make sure the database exists and authentication is ok" \ No newline at end of file