python flask sqlalchemy实现API,并解决复杂类的序列化

废话没有,直接code

postgreSQLORM.py

from sqlalchemy import create_engine,MetaData
from sqlalchemy import Integer,String,ForeignKey,Column
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import sqlalchemy
Base=declarative_base()
class con:
    def connect(user, password, db, host='localhost', port=5432):
        '''Returns a connection and a metadata object'''
        # We connect with the help of the PostgreSQL URL
        # postgresql://federer:grandestslam@localhost:5432/tennis
        url = 'postgresql://{}:{}@{}:{}/{}'
        url = url.format(user, password, host, port, db)

        # The return value of create_engine() is our connection object
        con = create_engine(url, client_encoding='utf8')

        # We then bind the connection to MetaData()
        meta = MetaData(bind=con)

        return con, meta


class child(Base):
    __tablename__='slamschild'
    value=Column(Integer)
    name=Column(String)
    id=Column(Integer,primary_key=True)

    def __init__(self,value,name,id):
        self.value=value
        self.name=name
        self.id=id
class res(Base):
    __tablename__='slams'
    value=Column(Integer,ForeignKey(child.value))
    name=Column(String,primary_key=True)
    country=Column(String)
    chi=relationship(child,uselist=True)
    def __init__(self,value,name,country):
        self.name=name
        self.value=value
        self.country=country



engine, meta = con.connect('postgres', 'postgres', 'postgres')

Base.metadata.bind = engine

DBSession = sessionmaker(bind=engine)

session = DBSession()

filmService.py

from flask import Blueprint
from flask import Flask, abort, request, jsonify
import json
from flask import jsonify
from sqlalchemy.ext.serializer import loads, dumps
import postgreSQLORM
from postgreSQLORM import res,child
film_api = Blueprint('film_api', __name__)


@film_api.route('/addfilm', methods=['POST'])
def addfilm():
    filmData = json.dumps(request.get_json(force=True))
    print(filmData)
    # ss=res(**json.loads(filmData))
    s=json.loads(filmData)
    chi=s["chi"]
    print(chi)
    s.pop('chi')
    print(s)
    ss=res(**s)
    try:
        for i in chi:
            rr=child(**i)
            postgreSQLORM.session.add(rr)
        postgreSQLORM.session.add(ss)
        postgreSQLORM.session.commit()
    except:
        postgreSQLORM.session.rollback()
    return filmData

@film_api.route('/getfilm/')
def getFilms(name):
    ss=postgreSQLORM.session.query(res).filter(res.name==name).one()
    return json.dumps(ss, cls=new_alchemy_encoder(), check_circular=False)

from sqlalchemy.ext.declarative import DeclarativeMeta

# class AlchemyEncoder(json.JSONEncoder):
#
#     def default(self, obj):
#         if isinstance(obj.__class__, DeclarativeMeta):
#             # an SQLAlchemy class
#             fields = {}
#             for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
#                 data = obj.__getattribute__(field)
#                 try:
#                     json.dumps(data) # this will fail on non-encodable values, like other classes
#                     fields[field] = data
#                 except TypeError:
#                     fields[field] = None
#             # a json-encodable dict
#             return fields
#
#         return json.JSONEncoder.default(self, obj)
'''This would encode all children, and all their children, and all their children... 
Potentially encode your entire database, 
basically. When it reaches something its encoded before, it will encode it as 'None'.'''
from sqlalchemy.ext.declarative import DeclarativeMeta
def new_alchemy_encoder():
        _visited_objs = []
        class AlchemyEncoder(json.JSONEncoder):
            def default(self, obj):
                if isinstance(obj.__class__, DeclarativeMeta):
                    # don't re-visit self
                    if obj in _visited_objs:
                        return None
                    _visited_objs.append(obj)
                    # an SQLAlchemy class
                    fields = {}
                    for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                        fields[field] = obj.__getattribute__(field)
                    # a json-encodable dict
                    return fields
                return json.JSONEncoder.default(self, obj)
        return AlchemyEncoder

main.py

from flask import Flask
from filmService import film_api

app = Flask(__name__)
app.register_blueprint(film_api, url_prefix='/film_api')


@app.route("/")
def service():
    return "Service is running!"


if __name__ == "__main__":
    app.run(port=500)

How to serialize SqlAlchemy result to JSON?
https://cmsdk.com/python/how-to-serialize-sqlalchemy-result-to-json.html

你可能感兴趣的:(Python)