2016-05-06 27 views
0

Ich habe eine Flask-RESTful-basierte API, die derzeit zwei Blueprints hat, so dass ich die API mit rückwärtskompatiblen Änderungen versionieren kann.Verschiedene Modell resource_fields für verschiedene Blueprints

from api_1_0 import api_bp as api_1_0_blueprint 
app.register_blueprint(api_1_0_blueprint, url_prefix='/api/v1.0') 

from api_1_1 import api_bp as api_1_1_blueprint 
app.register_blueprint(api_1_1_blueprint, url_prefix='/api/v1.1') 

Immer wenn ich eine rückwärtskompatible Änderung vornehmen muss (z. B. Entfernen eines Endpunkts), erstelle ich einen neuen Blueprint. Derzeit teilen sich die Blueprints die gleiche models.py Datei und definieren die Datenbanktabellen und die JSON-Darstellung jedes Modells.

Ich muss jetzt eine neue Version der API erstellen, in der ein bestimmtes Ressourcenfeld email von einem string Datentyp in array[string] geändert wird. Die vorhandenen Versionen der API müssen die ursprüngliche Ressourcendarstellung beibehalten.

ich versucht habe, in jedem Plan Ordner eine models.py Datei platzieren, so dass der neuere Entwurf v1.2 hat es selbst ist resource_fields Definition, aber dadurch ich mit diesem Fehler am Ende:

sqlalchemy.exc.InvalidRequestError: Table '' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

Ich verstehe, das ist passiert, weil ich im Grunde die gleichen Datenbanktabellen für jeden Bauplan definiere. Wirklich alles, was ich will, ist die resource_fields per Blueprint zu ändern, da das Datenbankschema über alle API-Versionen immer gleich sein wird, ist es nur die JSON-Antwort, die sich ändern kann. (Ich werde die @property Dekorateur verwenden, um die neuen Felder zu erstellen)

Angesichts dieser Einrichtung, wie kann ich die resource_fields per Blueprint ändern?

Unten finden Sie einen Beispielcode (vereinfacht) aus meinem Projekt.

app/models.py - https://gist.github.com/MattHealy/4c9d2c03615e3381774235bbbc398437

from app import db 
from flask.ext.restful import fields 

@swagger.model 
class Contact(db.Model): 

     resource_fields = { 
     'email': fields.String 
     } 

     email = db.Column(db.String(100)) 

app/api_1_1/resources/contacts.py - https://gist.github.com/MattHealy/556c93fe33a929e469ae18bf76db83b1

from flask.ext.restful import Resource, marshal, reqparse 
from ... models import Contact 

class ContactAPI(Resource): 

    "Retrieve details of a single contact" 
    @swagger.operation(
     nickname = "contact", 
     responseClass=Contact.__name__, 
     parameters=[ 
      { 
       "name": "id", 
       "description": "ID of the contact", 
       "required": True, 
       "allowMultiple": False, 
       "dataType": "int", 
       "paramType": "path" 
      }, 
     ], 
     responseMessages=[ 
      { 
       "code": 200, 
       "message": "Contact retrieved" 
      }, 
      ], 
     summary="Get details of a single contact", 
     ) 
    def get(self, id): 
     contact = Contact.query.get(id) 
     return { 'contact': marshal(contact, Contact.resource_fields) } 

Antwort

1

Sie können nur eine andere verwenden (lokal erzeugten) resource_fields dict pro Bauplan. In Ihrem speziellen Fall könnten Sie resource_fields als Attribut der Klasse ContactAPI verwenden und an die Marshalling-Funktion übergeben.

In dem speziellen Fall, den Sie oben zeigen (Änderung des Typs für das E-Mail-Feld) Ich denke, Sie müssen auch eine benutzerdefinierte Fields-Klasse erstellen (basierend auf fields.Raw), um die Art der Ausgabe, die Sie erhalten möchten .

Verwandte Themen