Aplicaciones de una sola p谩gina con Vue.js y Flask: API RESTful con Flask

    API RESTful con Flask

    Bienvenido a la cuarta publicaci贸n sobre el uso de Vue.js y Flask para el desarrollo web de pila completa. El enfoque de esta publicaci贸n ser谩 la creaci贸n de una API REST de backend utilizando el marco web Flask basado en Python.

    El c贸digo de esta publicaci贸n est谩 en un repositorio en mi cuenta de GitHub bajo la rama FourthPost.

    Contenido de la serie

    • Seup y familiarizaci贸n con VueJS
    • Navegando por el enrutador Vue
    • Gesti贸n de estado con Vuex
    • API RESTful con Flask (est谩s aqu铆)
    • Integraci贸n AJAX con API REST
    • Autenticaci贸n JWT
    • Implementaci贸n en un servidor privado virtual

    Breve explicaci贸n del matraz

    Flask es un micro-framework basado en Python para la creaci贸n r谩pida de prototipos y el desarrollo de aplicaciones web de tama帽o peque帽o a moderado. Flask ya se ha cubierto en un par de publicaciones anteriores aqu铆 y aqu铆 en Pharos.sh, por lo que no entrar茅 en grandes detalles sobre las partes b谩sicas o comunes de Flask. En su lugar, adoptar茅 un enfoque m谩s pragm谩tico que se centrar谩 principalmente en la construcci贸n de una API RESTful para alimentar la interfaz con datos, que cubr铆 en los art铆culos anteriores a este.

    Andamiaje de los archivos de proyecto de backend

    Empiezo en el directorio / backend creando un entorno virtual Python3 e instalando Flask y algunas otras bibliotecas necesarias.

    $ python -m venv venv
    $ source venv/bin/activate
    (venv) $ pip install Flask Flask-SQLAlchemy Flask-Migrate Flask-Script requests
    

    Una cosa que hace que Flask (y en gran parte todo el ecosistema de Python) sea tan asombroso es la gran cantidad de paquetes bien dise帽ados disponibles en PyPI. A continuaci贸n se muestra una breve explicaci贸n de las bibliotecas que instal茅 y su uso previsto.

    • Matraz: micro marco web
    • Flask-SQLAlchemy: ORM basado en SQLAlchemy con una salsa incre铆ble espec铆fica de Flask empaquetada con 茅l
    • Flask-Migrate: biblioteca de migraci贸n de bases de datos
    • Flask-Script: paquete extremadamente 煤til para interactuar con una aplicaci贸n Flask desde la l铆nea de comandos
    • solicitudes: un paquete 煤til para realizar solicitudes de red que usar茅 para probar la API REST

    En el directorio / backend hago algunos archivos nuevos llamados manage.py y appserver.py. Adem谩s, crear茅 un nuevo directorio dentro de / backend que se convertir谩 en mi aplicaci贸n Flask “surveyyapi”. Dentro del directorio surveyyapi hago los archivos __init__.py, models.py, application.py y api.py. Esto da como resultado una estructura de directorio que comienza en / backend as铆 (omitiendo el directorio venv).

    鈹溾攢鈹 manage.py
    鈹溾攢鈹 appserver.py
    鈹斺攢鈹 surveyapi
        鈹溾攢鈹 __init__.py
        鈹溾攢鈹 api.py
        鈹溾攢鈹 application.py
        鈹溾攢鈹 config.py
        鈹斺攢鈹 models.py
    

    A continuaci贸n se muestra una breve descripci贸n de para qu茅 se utilizar谩 cada archivo:

    • manage.py: acceso a la instancia de la aplicaci贸n Flask para varios comandos Flask-Script
    • appserver.py: script de inicio para ejecutar la aplicaci贸n surveyyapi
    • surveyyapi /: la aplicaci贸n backend Flask
    • __init__.py: convierte el directorio surveyyapi en un paquete Python v谩lido
    • api.py: para definir puntos finales de ruta de API REST capaces de consumir y producir solicitudes y respuestas JSON
    • application.py: para crear una instancia de la aplicaci贸n Flask
    • config.py: contiene opciones de configuraci贸n para la aplicaci贸n Flask
    • models.py: para definir clases que servir谩n como objetos de datos para la aplicaci贸n de encuestas, como Encuesta, Pregunta y Elecci贸n

    Crear una f谩brica de aplicaciones

    Comenzar茅 a codificar la aplicaci贸n surveyyapi definiendo algunas configuraciones dentro de config.py as铆:

    """
    config.py
    - settings for the flask application object
    """
    
    class BaseConfig(object):
        DEBUG = True
        SQLALCHEMY_DATABASE_URI = 'sqlite:///survey.db'
        SQLALCHEMY_TRACK_MODIFICATIONS = False
        # used for encryption and session management
        SECRET_KEY = 'mysecretkey'
    

    Esta clase de configuraci贸n define un SQLALCHEMY_DATABASE_URI URI de conexi贸n de la base de datos de la aplicaci贸n a una base de datos SQLite de un solo archivo llamada survey.db. Tambi茅n proporciona SECRET_KEY opci贸n de configuraci贸n que se utiliza para el cifrado.

    Dentro de application.py, crear茅 lo que se conoce como una funci贸n de f谩brica de aplicaciones, que hace exactamente lo que parece, crea una instancia de aplicaci贸n Flask. Adem谩s de crear una instancia de Flask, tambi茅n obtiene el BaseConfig objeto y registra el plano de rutas API que har茅 a continuaci贸n.

    """
    application.py
    - creates a Flask app instance and registers the database object
    """
    
    from flask import Flask
    
    def create_app(app_name="SURVEY_API"):
        app = Flask(app_name)
        app.config.from_object('surveyapi.config.BaseConfig')
        from surveyapi.api import api
        app.register_blueprint(api, url_prefix="/api")
        return app
    

    API de planos

    A continuaci贸n, me mover茅 al m贸dulo api.py donde puedo definir un Blueprint objeto llamado api que contiene rutas RESTful. Para mantener las cosas simples, comenzar茅 simplemente definiendo una funci贸n de vista simple llamada say_hello() asociado con el punto final /api/hello/<string:name>/. los <string:name> parte de la URL es una variable de cadena din谩mica que se pasa a la funci贸n de vista say_hello(name) como un par谩metro de funci贸n que utilizo en el mensaje de respuesta JSON que se devuelve.

    """
    api.py
    - provides the API endpoints for consuming and producing
      REST requests and responses
    """
    
    from flask import Blueprint, jsonify, request
    
    api = Blueprint('api', __name__)
    
    @api.route('/hello/<string:name>/')
    def say_hello(name):
        response = { 'msg': "Hello {}".format(name) }
        return jsonify(response)
    

    Punto de entrada del servidor de desarrollo y validaci贸n de la configuraci贸n

    Para probar esto, necesito agregar un par de l铆neas de c贸digo en appserver.py para crear una instancia de la aplicaci贸n. Esto me permite iniciar el servidor de desarrollo de Flask llamando al run() m茅todo en el app ejemplo.

    """
    appserver.py
    - creates an application instance and runs the dev server
    """
    
    if __name__ == '__main__':
        from surveyapi.application import create_app
        app = create_app()
        app.run()
    

    Para ejecutar el servidor de desarrollo Flask, todo lo que tengo que hacer es iniciar el int茅rprete de Python y alimentarlo con el script appserver.py como se muestra a continuaci贸n.

    (venv) $ python appserver.py
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
     * Restarting with stat
     * Debugger is active!
     * Debugger PIN: 676-284-544
    

    Ahora, para probar el nuevo punto final, en una nueva terminal con el entorno virtual activado, encender茅 un int茅rprete de Python y har茅 una solicitud GET para http://localhost:5000/api/hello/adam/ utilizando el requests paquete.

    (venv) $ python
    >>> import requests
    >>> response = requests.get('http://localhost:5000/api/hello/adam/')
    >>> print(response.json())
    {'msg': 'Hello adam'}
    

    Definici贸n de la capa de datos

    Ahora que he verificado que tengo una aplicaci贸n de Flask en funcionamiento, puedo concentrarme en construir la capa de datos con la ayuda del ORM de Flask-SQLAlchemy. La implementaci贸n de una capa de datos requerir谩 escribir algunas clases de datos dentro de models.py como:

    • Encuesta: este es el objeto de nivel superior que contendr谩 una o m谩s preguntas junto con sus opciones
    • Pregunta: objetos que pertenecen a un objeto de encuesta y contienen opciones
    • Elecci贸n: objetos que pertenecen a una pregunta y representan opciones para la pregunta de la encuesta.

    Estas clases de datos plantear谩n campos que en gran parte imitar谩n los descritos anteriormente en los art铆culos sobre la construcci贸n de la aplicaci贸n frontend Vue.js, pero estos se asignar谩n a las tablas de la base de datos donde se conservar谩n sus datos.

    """
    models.py
    - Data classes for the surveyapi application
    """
    
    from datetime import datetime
    from flask_sqlalchemy import SQLAlchemy
    
    db = SQLAlchemy()
    
    class Survey(db.Model):
        __tablename__ = 'surveys'
    
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.Text)
        created_at = db.Column(db.DateTime, default=datetime.utcnow)
        questions = db.relationship('Question', backref="survey", lazy=False)
    
        def to_dict(self):
            return dict(id=self.id,
                        name=self.name,
                        created_at=self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                        questions=[question.to_dict() for question in self.questions])
    
    class Question(db.Model):
        __tablename__ = 'questions'
    
        id = db.Column(db.Integer, primary_key=True)
        text = db.Column(db.String(500), nullable=False)
        created_at = db.Column(db.DateTime, default=datetime.utcnow)
        survey_id = db.Column(db.Integer, db.ForeignKey('surveys.id'))
        choices = db.relationship('Choice', backref="question", lazy=False)
    
        def to_dict(self):
            return dict(id=self.id,
                        text=self.text,
                        created_at=self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                        survey_id=self.survey_id,
                        choices=[choice.to_dict() for choice in self.choices])
    
    class Choice(db.Model):
        __tablename__ = 'choices'
    
        id = db.Column(db.Integer, primary_key=True)
        text = db.Column(db.String(100), nullable=False)
        selected = db.Column(db.Integer, default=0)
        created_at = db.Column(db.DateTime, default=datetime.utcnow)
        question_id = db.Column(db.Integer, db.ForeignKey('questions.id'))
    
        def to_dict(self):
            return dict(id=self.id,
                        text=self.text,
                        created_at=self.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                        question_id=self.question_id)
    
    

    Como se mencion贸 anteriormente, estoy usando la extensi贸n espec铆fica de Flask de SQLAlchemy llamada Matraz-SQLAlchemy para alimentar el ORM para esta aplicaci贸n. Me gusta Flask-SQLAlchemy porque tiene una API bastante Pythonic y proporciona valores predeterminados sensibles para definir y trabajar con clases de datos.

    Cada clase hereda de la SQLAlchemy Model clase base que proporciona m茅todos de utilidad intuitivos y legibles para interactuar con los datos almacenados en la base de datos. Adem谩s, cada clase se compone de una serie de campos de clase que se traducen en campos de la tabla de la base de datos seg煤n lo especificado por SQLAlchemy Column clase y tipo asociado (es decir, Integer, String, DateTime, Text, …).

    Tambi茅n notar谩 que cada clase tiene un to_dict() m茅todo. Este m茅todo ser谩 煤til para serializar los datos de los modelos en JSON al enviarlos por cable al cliente frontend.

    El siguiente paso en la lista es registrar el objeto SQLAlchemy, db, con el objeto de aplicaci贸n Flask en application.py.

    """
    application.py
    - creates a Flask app instance and registers the database object
    """
    
    from flask import Flask
    
    def create_app(app_name="SURVEY_API"):
        app = Flask(app_name)
        app.config.from_object('surveyapi.config.BaseConfig')
    
        from surveyapi.api import api
        app.register_blueprint(api, url_prefix="/api")
    
        from surveyapi.models import db
        db.init_app(app)
    
        return app
    
    

    Lo 煤ltimo que me gustar铆a hacer es reunir a los Frasco-Script y Frasco-Migrar paquetes de extensi贸n dentro del m贸dulo manage.py para permitir migraciones. Este pr谩ctico m贸dulo, manage.py, reunir谩 las clases de datos que acabo de definir y las vincular谩 al contexto de la aplicaci贸n junto con la maquinaria Flask-Migrate y Flask-Script.

    """
    manage.py
    - provides a command line utility for interacting with the
      application to perform interactive debugging and setup
    """
    
    from flask_script import Manager
    from flask_migrate import Migrate, MigrateCommand
    
    from surveyapi.application import create_app
    from surveyapi.models import db, Survey, Question, Choice
    
    app = create_app()
    
    migrate = Migrate(app, db)
    manager = Manager(app)
    
    # provide a migration utility command
    manager.add_command('db', MigrateCommand)
    
    # enable python shell with application context
    @manager.shell
    def shell_ctx():
        return dict(app=app,
                    db=db,
                    Survey=Survey,
                    Question=Question,
                    Choice=Choice)
    
    if __name__ == '__main__':
        manager.run()
    

    Estoy logrando dos cosas en este fragmento de c贸digo anterior. Primero, estoy creando una instancia del objeto de aplicaci贸n Flask para que proporcione contexto al Migrate(app, db) y Manage(app) instancias. Luego estoy agregando un comando al manager objeto que me permite crear y ejecutar migraciones desde la l铆nea de comando as铆:

    (venv) $ python manage.py db init
    
    • Inicialice el directorio de migraciones junto a la aplicaci贸n y el archivo de base de datos de survey.db
    (venv) $ python manage.py db migrate
    
    • Cree un archivo de migraci贸n inicial para traducir las clases en models.py a SQL que generar谩 las tablas correspondientes
    (venv) $ python manage.py db upgrade
    
    • Ejecute la migraci贸n para actualizar la base de datos con las tablas descritas en el paso anterior

    Lo 煤ltimo que estoy haciendo en el m贸dulo manage.py es crear otro comando personalizado utilizando @manager.shell para decorar un shell_ctx() funci贸n que devuelve una palabra clave de asignaci贸n de dict a la app y db objetos junto con el Survey, Question y, Choice clases de datos.

    Ahora aprovechar茅 la utilidad de este comando de utilidad de shell para demostrar c贸mo trabajar con el ORM Flask-SQLAlchemy dentro del int茅rprete de Python que produce.

    (venv) $ python manage.py shell
    (venv) Adams-MacBook-Pro:backend adammcquistan$ python manage.py shell
    >>> survey = Survey(name="Dogs")
    >>> question = Question(text="What is your favorite dog?")
    >>> question.choices = [Choice(text="Beagle"), Choice(text="Rottweiler"), Choice(text="Labrador")]
    >>> question2 = Question(text="What is your second favorite dog?")
    >>> question2.choices = [Choice(text="Beagle"), Choice(text="Rottweiler"), Choice(text="Labrador")]
    >>> survey.questions = [question, question2]
    >>> db.session.add(survey)
    >>> db.session.commit()
    >>> surveys = Survey.query.all()
    >>> for s in surveys:
    ...     print('Survey(id={}, name={})'.format(s.id, s.name))
    ...     for q in s.questions:
    ...             print('  Question(id={}, text={})'.format(q.id, q.text))
    ...             for c in q.choices:
    ...                     print('    Choice(id={}, text={})'.format(c.id, c.text))
    ...
    Survey(id=1, name=Dogs)
      Question(id=1, text=What is your favorite dog?)
        Choice(id=1, text=Beagle)
        Choice(id=3, text=Labrador)
        Choice(id=2, text=Rottweiler)
      Question(id=2, text=What is your second favorite dog?)
        Choice(id=4, text=Beagle)
        Choice(id=6, text=Labrador)
        Choice(id=5, text=Rottweiler)
    

    Eso es bastante h谩bil, 驴verdad?

    No me refiero solo a la sintaxis elegante y legible del ORM, sino a la capacidad incre铆blemente poderosa de activar un int茅rprete de Python que contiene el contexto de la aplicaci贸n para hacer peque帽os experimentos r谩pidos con los modelos de su aplicaci贸n. No puedo decirle cu谩nto aumento de productividad me ha proporcionado esto al crear aplicaciones de backend, y le sugiero seriamente que lo utilice al hacer lo mismo.

    Completando la API RESTful

    Ahora que la capa de acceso a datos est谩 construida, puedo enfocar mi atenci贸n en completar la implementaci贸n necesaria para la API RESTful. Esto manejar谩 el consumo y la devoluci贸n de los recursos de la aplicaci贸n, como los datos de la encuesta, la pregunta y la elecci贸n. Los casos de uso requeridos de la API RESTful incluyen lo siguiente:

    • Obtenga todas las encuestas junto con sus preguntas y opciones
    • Obtenga una sola encuesta junto con sus preguntas y opciones
    • Cree una nueva encuesta junto con sus preguntas y opciones espec铆ficas
    • Actualizar las opciones de respuesta de una encuesta una vez que se ha realizado una encuesta

    Para empezar, seguir茅 adelante e importar茅 todas las clases de datos junto con SQLAlchemy db instancia para que tenga acceso a ellos. En la parte superior de api.py agrego las siguientes importaciones:

    """
    api.py
    - provides the API endpoints for consuming and producing
      REST requests and responses
    """
    
    from flask import Blueprint, jsonify, request
    from .models import db, Survey, Question, Choice
    

    En cuanto a los puntos finales de recursos reales, comenzar茅 codificando la capacidad de obtener todos los recursos de la encuesta. Dentro de api.py necesito reemplazar el /hello/<string:name>/ punto final con la ruta /surveys/ punto final y surveys() funci贸n de visualizaci贸n.

    @api.route('/surveys/')
    def surveys():
        surveys = Survey.query.all()
        return jsonify({ 'surveys': [s.to_dict() for s in surveys] })
    

    Si el servidor de desarrollo a煤n se est谩 ejecutando, una vez que guarde los archivos del proyecto, el servidor deber铆a recargarse autom谩ticamente y actualizar todos los cambios. Si no, entonces corriendo (venv) $ python appserver.py iniciar谩 el servidor. Ahora en otro terminal con el entorno virtual activado puedo usar el requests paquete para probar este nuevo punto final. Sin embargo, me gustar铆a compartir un consejo profesional sobre c贸mo mostrar respuestas JSON de una manera m谩s legible mediante el uso de otro paquete de Python impresionante llamado pprint.

    (venv) $ pip install pprint
    (venv) $ python
    >>> import pprint, requests
    >>> pp == pprint.PrettyPrinter()
    >>> resp = requests.get('http://localhost:5000/api/surveys/')
    >>> pp.pprint(resp.json())
    {'surveys': [{
         'created_at': '2018-03-06 03:52:44',
         'id': 1,
         'name': 'Dogs',
         'questions': [{
              'choices': [{
                   'created_at': '2018-03-06 03:52:44',
                   'id': 1,
                   'question_id': 1,
                   'text': 'Beagle'
                  },{
                   'created_at': '2018-03-06 03:52:44',
                   'id': 3,
                   'question_id': 1,
                   'text': 'Labrador'
                  },{
                   'created_at': '2018-03-06 03:52:44',
                   'id': 2,
                   'question_id': 1,
                   'text': 'Rottweiler'}],
                'created_at': '2018-03-06 03:52:44',
                'id': 1,
                'survey_id': 1,
                'text': 'What is your favorite dog?'
             },{
              'choices': [{
                  'created_at': '2018-03-06 03:52:44',
                  'id': 4,
                  'question_id': 2,
                  'text': 'Beagle'
                 },{
                  'created_at': '2018-03-06 03:52:44',
                  'id': 6,
                  'question_id': 2,
                  'text': 'Labrador'
                 },{
                  'created_at': '2018-03-06 03:52:44',
                  'id': 5,
                  'question_id': 2,
                  'text': 'Rottweiler'}],
              'created_at': '2018-03-06 03:52:44',
              'id': 2,
              'survey_id': 1,
              'text': 'What is your second favorite dog?'}]}
        ]}
    

    A continuaci贸n, implementar茅 la funcionalidad para obtener una sola encuesta por su id con el extremo de la URL /surveys/id/ y ver la funci贸n survey(id). Inmediatamente despu茅s de la surveys() Funci贸n de vista API coloco el siguiente c贸digo:

    @api.route('/surveys/<int:id>/')
    def survey(id):
        survey = Survey.query.get(id)
        return jsonify({ 'survey': survey.to_dict() })
    

    Nuevamente, guardar茅 los archivos y probar茅 el nuevo punto final de la API para asegurarme de que brinde una respuesta v谩lida.

    >>> resp = requests.get('http://localhost:5000/api/surveys/1/')
    >>> pp.pprint(resp.json())
    {'survey': {
         'created_at': '2018-03-06 03:52:44',
         'id': 1,
         'name': 'Dogs',
         'questions': [{
              'choices': [{
                   'created_at': '2018-03-06 03:52:44',
                   'id': 1,
                   'question_id': 1,
                   'text': 'Beagle'
                  },{
                   'created_at': '2018-03-06 03:52:44',
                   'id': 3,
                   'question_id': 1,
                   'text': 'Labrador'
                  },{
                   'created_at': '2018-03-06 03:52:44',
                   'id': 2,
                   'question_id': 1,
                   'text': 'Rottweiler'}],
                'created_at': '2018-03-06 03:52:44',
                'id': 1,
                'survey_id': 1,
                'text': 'What is your favorite dog?'
             },{
              'choices': [{
                  'created_at': '2018-03-06 03:52:44',
                  'id': 4,
                  'question_id': 2,
                  'text': 'Beagle'
                 },{
                  'created_at': '2018-03-06 03:52:44',
                  'id': 6,
                  'question_id': 2,
                  'text': 'Labrador'
                 },{
                  'created_at': '2018-03-06 03:52:44',
                  'id': 5,
                  'question_id': 2,
                  'text': 'Rottweiler'}],
              'created_at': '2018-03-06 03:52:44',
              'id': 2,
              'survey_id': 1,
              'text': 'What is your second favorite dog?'}]}
        }
    

    Hasta ahora, solo he utilizado el m茅todo de ruta HTTP GET predeterminado adecuado para obtener datos de las API RESTful. Sin embargo, para las dos 煤ltimas funciones, necesitar茅 utilizar los m茅todos HTTP POST y PUT para los puntos finales /api/surveys/ y /api/surveys/id/, respectivamente. Usar茅 el m茅todo HTTP POST para crear nuevas encuestas y el m茅todo HTTP PUT para actualizar una encuesta existente con un nuevo conjunto de opciones de respuesta seleccionadas.

    Para el /api/surveys/ ruta Necesitar茅 agregar un par谩metro de m茅todo a la declaraci贸n de ruta para especificar que acepta los m茅todos GET y POST, methods=('GET','POST'). Adem谩s modificar茅 el cuerpo del surveys() Ver funci贸n para diferenciar el tipo de m茅todo y agregar la capacidad de guardar una nueva encuesta en la base de datos.

    @api.route('/surveys/', methods=('GET', 'POST'))
    def fetch_surveys():
        if request.method == 'GET':
            surveys = Survey.query.all()
            return jsonify({ 'surveys': [s.to_dict() for s in surveys] })
        elif request.method == 'POST':
            data = request.get_json()
            survey = Survey(name=data['name'])
            questions = []
            for q in data['questions']:
                question = Question(text=q['text'])
                question.choices = [Choice(text=c['text'])
                                    for c in q['choices']]
                questions.append(question)
            survey.questions = questions
            db.session.add(survey)
            db.session.commit()
            return jsonify(survey.to_dict()), 201
    

    Nuevamente, querr茅 guardar el proyecto y probarlo para asegurarme de tener un recurso de ahorro de encuestas completamente funcional.

    >>> import json
    >>> survey = {
    ...   'name': 'Cars',
    ...   'questions': [{
    ...     'text': 'What is your favorite car?',
    ...     'choices': [
    ...       { 'text': 'Corvette' },
    ...       { 'text': 'Mustang' },
    ...       { 'text': 'Camaro' }]
    ...   }, {
    ...     'text': 'What is your second favorite car?',
    ...     'choices': [
    ...       { 'text': 'Corvette' },
    ...       { 'text': 'Mustang' },
    ...       { 'text': 'Camaro' }]
    ...   }]
    ... }
    >>> headers = {'Content-type': 'application/json'}
    >>> resp = requests.post('http://localhost:5000/api/surveys/', headers=headers, data=json.dumps(survey))
    >>> resp.status_code
    201
    

    La 煤ltima pieza a implementar es la capacidad de actualizar una encuesta existente con nuevas selecciones de respuesta a la encuesta. Nuevamente, tendr茅 que agregar los m茅todos de GET y PUT al /api/surveys/id/ definici贸n de ruta, methods=('GET', 'PUT'). Entonces actualizo el survey(id) Ver funci贸n para actualizar las opciones de preguntas de la encuesta asociada especificadas como seleccionadas en el cuerpo JSON de la solicitud PUT.

    @api.route('/surveys/<int:id>/', methods=('GET', 'PUT'))
    def survey(id):
        if request.method == 'GET':
            survey = Survey.query.get(id)
            return jsonify({ 'survey': survey.to_dict() })
        elif request.method == 'PUT':
            data = request.get_json()
            for q in data['questions']:
                choice = Choice.query.get(q['choice'])
                choice.selected = choice.selected + 1
            db.session.commit()
            survey = Survey.query.get(data['id'])
            return jsonify(survey.to_dict()), 201
    

    Por 煤ltimo, necesito guardar todos mis archivos y hacer una prueba final como esta:

    >>> survey_choices = {
    ...   'id': 1,
    ...   'name': 'Dogs',
    ...   'questions': [
    ...     { 'id': 1, 'choice': 1 },
    ...     { 'id': 2, 'choice': 5 }]
    ... }
    >>> headers = {'Content-type': 'application/json'}
    >>> resp = requests.put('http://localhost:5000/api/surveys/1/', data=json.dumps(survey_choices), headers=headers)
    >>> resp.status_code()
    201
    

    Conclusi贸n

    En este art铆culo he cubierto c贸mo implementar una API RESTful simple, bastante b谩sica, usando Flask de acuerdo con la siguiente tabla:

    Funcionalidad del m茅todo de ruta

    / api / survey /OBTENERRecuperar todas las encuestas
    / api / survey /ENVIARCrea una nueva encuesta
    / api / survey / id /OBTENERRecuperar una encuesta por id
    / api / survey / id /PONERActualizar las selecciones de opciones de una encuesta

    En el pr贸ximo art铆culo, demostrar茅 c贸mo integrar la aplicaci贸n frontend Vue.js para que pueda consumir y enviar actualizaciones de datos al backend de Flask.

    Como siempre, gracias por leer y no dude en comentar o criticar a continuaci贸n.

     

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *