【问题标题】:Using python library flask-rest-jsonapi without id as primary key使用没有id作为主键的python库flask-rest-jsonapi
【发布时间】:2019-09-04 23:44:20
【问题描述】:

我正在使用 Python 库 flask-rest-jsonapi 来设计 API。该库使用flask-sqlalchemymarshmallow。 Marshmallow 要求架构中必须有一个“id”和一个“type”字段。

我为其设计 API 的数据库表没有“id”列。我试图定义关系的两张表称为部门和教师,其中一个部门有多名教师,因此部门和教师之间存在一对多的关系。它们的主键列称为“Department_Unique_ID”和“Teacher_Unique_ID”。

这是我的代码:

from flask import Flask
from flask_rest_jsonapi import Api, ResourceDetail, ResourceList, ResourceRelationship
from flask_rest_jsonapi.exceptions import ObjectNotFound
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm.exc import NoResultFound
from marshmallow_jsonapi.flask import Schema, Relationship
from marshmallow_jsonapi import fields
import connectDB

# Create the Flask application
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

app = connectDB.connectToDb(app)

db = SQLAlchemy(app)

class Department(db.Model):
    db.Model.metadata.schema = 'UNIVERSITY'
    __tablename__ = 'Department'
    Department_Unique_ID = db.Column(db.String, primary_key=True)
    Department_Name = db.Column(db.String)
    uni_teacher = db.relationship('Teacher', backref=db.backref('Department'))

    __mapper_args__ = {
        "order_by":Department_Unique_ID
    }

class Teacher(db.Model):
    db.Model.metadata.schema = 'UNIVERSITY'
    __tablename__ = 'Teacher'
    Teacher_Unique_ID = db.Column(db.String, primary_key=True)
    Teacher_Name = db.Column(db.String)
    Department_ID_Unique = db.Column(db.String, db.ForeignKey('Department.Department_Unique_ID'))

    __mapper_args__ = {
        "order_by":Teacher_Unique_ID
    }

class DepartmentSchema(Schema):
    class Meta:
        type_ = 'uni_department'
        self_view = 'uni_department_detail'
        self_view_kwargs = {'id': '<Department_Unique_ID>'}
        self_view_many = 'uni_department_list'
        strict = True
        __model__ = Department

    id = fields.Integer(as_string=True, many=True, dump_only=True) #not used, if I remove this, I get an error "Must have an 'id' field"

    Department_Unique_ID = fields.Str()
    Department_Name = fields.Str()
    uni_teacher = Relationship(self_view='uni_department_uni_teacher',
                             self_view_kwargs={'id':'<Department_Unique_ID>'},
                             related_view='uni_teacher_list',
                             related_view_kwargs={'id':'<Department_Unique_ID>'},
                             many=True,
                             schema='TeacherSchema',
                             type_='uni_teacher',
                              id_field='Teacher_Unique_ID')

class TeacherSchema(Schema):
    class Meta:
        type_ = 'uni_teacher'
        self_view = 'uni_teacher_detail'
        self_view_kwargs = {'id': '<Teacher_Unique_ID>'}
        self_view_many = 'uni_teacher_list'
        strict = True
        __model__ = Teacher

    id = fields.Integer(as_string=True, many=True, dump_only=True) #not used, if I remove this, I get an error "Must have an 'id' field"

    Teacher_Unique_ID = fields.Str()
    Teacher_Name = fields.Str()
    owner = Relationship(attribute='uni_department',
                         self_view='uni_teacher_uni_department',
                         self_view_kwargs={'id':'<Teacher_Unique_ID>'},
                         related_view='uni_department_detail',
                         related_view_kwargs={'id':'<Department_Unique_ID>'},
                         schema='DepartmentSchema',
                         type_='uni_department')

class DepartmentList(ResourceList):
    schema = DepartmentSchema
    data_layer = {'session': db.session,
                  'model': Department}


class TeacherList(ResourceList):
    def query(self, view_kwargs):
        query_ = self.session.query(Teacher)
        if view_kwargs.get('Teacher_Unique_ID') is not None:
            try:
                self.session.query(Department).filter_by(Teacher_Unique_ID=view_kwargs['Teacher_Unique_ID']).one()
            except NoResultFound:
                raise ObjectNotFound({'parameter': 'Teacher_Unique_ID'}, "Teacher: {} not found".format(view_kwargs['Teacher_Unique_ID']))
            else:
                query_ = query_.join(Department).filter(Department.id == view_kwargs['Teacher_Unique_ID'])
        return query_

    def before_create_object(self, data, view_kwargs):
        if view_kwargs.get('Teacher_Unique_ID') is not None:
            uni_department = self.session.query(Department).filter_by(Teacher_Unique_ID=view_kwargs['Department_Unique_ID']).one()
            data['Department_Unique_ID'] = uni_department.Department_Unique_ID

    schema = TeacherSchema
    data_layer = {'session': db.session,
                  'model': Teacher}

class DepartmentDetail(ResourceDetail):
    def before_get_object(self, view_kwargs):
        if view_kwargs.get('Teacher_Unique_ID') is not None:
            try:
                uni_teacher = self.session.query(Teacher).filter_by(Department_Unique_ID=view_kwargs['Department_Unique_ID']).one()
            except NoResultFound:
                raise ObjectNotFound({'parameter': 'Department_Unique_ID'},
                                     "Teacher: {} not found".format(view_kwargs['Department_Unique_ID']))
            else:
                if uni_teacher.uni_department is not None:
                    view_kwargs['Department_Unique_ID'] = uni_teacher.uni_department.Department_Unique_ID
                else:
                    view_kwargs['Department_Unique_ID'] = None

    schema = DepartmentSchema
    data_layer = {'session': db.session,
                  'model': Department}


class TeacherDetail(ResourceDetail):
    schema = TeacherSchema
    data_layer = {'session': db.session,
                  'model': Teacher}

class DepartmentRelationship(ResourceRelationship):
    schema = DepartmentSchema
    data_layer = {'session': db.session,
                  'model': Department}

class TeacherRelationship(ResourceRelationship):
    schema = TeacherSchema
    data_layer = {'session': db.session,
                  'model': Teacher}

api = Api(app)
api.route(DepartmentList, 'uni_department_list', '/uni_department')
api.route(TeacherList, 'uni_teacher_list', '/uni_teacher', '/uni_teacher/<int:Department_Unique_ID>/uni_teacher')

api.route(DepartmentDetail, 'uni_department_detail', '/uni_department/<int:Department_Unique_ID>', '/uni_teacher/<int:Department_ID_Unique>/owner')
api.route(TeacherDetail, 'uni_teacher_detail', '/uni_teacher/<int:Teacher_Unique_ID>')

api.route(DepartmentRelationship, 'uni_department_uni_teacher', '/uni_department/<int:Department_Unique_ID>/relationships/uni_teacher')
api.route(TeacherRelationship, 'uni_teacher_uni_department', '/uni_teacher/<int:Teacher_Unique_Department>/relationships/owner')

if __name__ == '__main__':
    # Start application
    app.debug = True
    app.run()

我正在遵循flask-rest-jsonapi 的示例。任何帮助将不胜感激。

EDIT1- 这是请求的 connectDB.py 代码-

import yaml

def readDbDetails():
    with open('database_config.yaml', 'r') as stream:
        return (yaml.load(stream))


dbDetails = readDbDetails()


def connectToDb(app):

    database_host = dbDetails['database_host']
    database_username = dbDetails['database_username']
    database_name = dbDetails['database_name']
    database_password = dbDetails['database_password']
    database_port = dbDetails['database_port']
    print(database_host)
    print(database_name)
    print(database_username)
    print(database_password)
    print(database_port)

    app.config[
        'SQLALCHEMY_DATABASE_URI'] = 'mssql+pymssql://'+database_username+':'+database_password+'@'+database_host+':'+database_port+'/'+database_name+''

    return app

【问题讨论】:

  • 问题中能否包含connectToDb(app)的内容?
  • @arsho 我已经用 connectToDb(app) 代码更新了这个问题。

标签: python flask sqlalchemy flask-sqlalchemy marshmallow


【解决方案1】:

您可以使用 attribute 属性并将主键分配给该 id 字段

class DepartmentSchema(Schema):
    class Meta:
        type_ = 'uni_department'
        self_view = 'uni_department_detail'
        self_view_kwargs = {'id': '<Department_Unique_ID>'}
        self_view_many = 'uni_department_list'
        strict = True
        __model__ = Department

    id = fields.Integer(attribute='Department_Unique_ID', as_string=True, many=True, dump_only=True)

    Department_Unique_ID = fields.Str()
    Department_Name = fields.Str()
    uni_teacher = Relationship(self_view='uni_department_uni_teacher',
                               self_view_kwargs={'id': '<Department_Unique_ID>'},
                               related_view='uni_teacher_list',
                               related_view_kwargs={'id': '<Department_Unique_ID>'},
                               many=True,
                               schema='TeacherSchema',
                               type_='uni_teacher',
                               id_field='Teacher_Unique_ID')


class TeacherSchema(Schema):
    class Meta:
        type_ = 'uni_teacher'
        self_view = 'uni_teacher_detail'
        self_view_kwargs = {'id': '<Teacher_Unique_ID>'}
        self_view_many = 'uni_teacher_list'
        strict = True
        __model__ = Teacher

    id = fields.Integer(attribute='Teacher_Unique_ID', as_string=True, many=True, dump_only=True)

    Teacher_Unique_ID = fields.Str()
    Teacher_Name = fields.Str()
    owner = Relationship(attribute='uni_department',
                         self_view='uni_teacher_uni_department',
                         self_view_kwargs={'id': '<Teacher_Unique_ID>'},
                         related_view='uni_department_detail',
                         related_view_kwargs={'id': '<Department_Unique_ID>'},
                         schema='DepartmentSchema',
                         type_='uni_department')

【讨论】:

    猜你喜欢
    • 2019-04-24
    • 1970-01-01
    • 2022-01-22
    • 2011-09-26
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多