SQLAlchemy присоединиться к 2 таблице

я хочу создать python SQLAlchemy, это 2 таблицы в моей базе данных,

table name : student

- id (integer)

-  student_name (varchar(20))

- edu_level_id (integer)

содержать запись

id |  student_name  | edu_level_id

1  |  John  | 2

2  |  George | 1

таблица: master_edu_level

* id (integer)
* name_level (varchar(50))

записывать :

id  |  name_level  |   

1   |  high school

2   |  Bachelor

3 |  Master

как показать запись типа:

id |  student_name   | education


1  | John     | Bachelor

2  |  George  | high school

если я объясню SQL так:

select student.id, student.name,master_edu_level.name AS educatio FROM student
left join master_edu_Level ON master_edu_level.id = student.edu_level_id

Я уже пишу код:

from app import db
from app import session
from sqlalchemy import Table, DateTime,Date, Text, text, Column, Integer, String, MetaData, ForeignKey, select, func
from sqlalchemy.ext.declarative import declarative_base
from marshmallow_jsonapi import Schema, fields
from marshmallow import validate
from marshmallow import ValidationError
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import relationship

class Student(db.Model):
        __tablename__ = 'student'

        id = db.Column(Integer, primary_key=True, index=True)
        student_name = db.Column(String(20), nullable=False, index=True)
        edu_level_id = db.Column(Integer)

class StudentSchema(Schema):
    not_blank = validate.Length(min=1, error='Field cannot be blank')
    id = fields.Integer(dump_only=True)
    student_name        = fields.String()  
    edu_level_id        = fields.String()  

    class Meta:
        type_ = 'student'

student_schema = StudentSchema()  


class MasterEduLevel(db.Model):
    __tablename__ = 'master_edu_level'
    __table_args__ = {'extend_existing': True} 

    id = db.Column(Integer, primary_key=True, index=True)
    name_level = db.Column(String(20), nullable=False, index=True)


class MasterEdulevelSchema(Schema):
    not_blank = validate.Length(min=1, error='Field cannot be blank')
    id = fields.Integer(dump_only=True)
    name_level        = fields.String()  

    class Meta:
        type_ = 'master_edu_level'

schema = MasterEdulevelSchema()

как создать таблицу соединений ORM на python SQLAlchemy?

спасибо


person helo1987    schedule 16.01.2017    source источник
comment
Вы действительно можете создавать сопоставления на поверх соединений, но действительно ли вы хотели добавить отношение в Student, чтобы вы могли, например, получить к нему доступ, как student.edu_level.name_level, или как выполнить запрос, например query(Student.student_name, MasterEduLevel.name_level).join(MasterEduLevel)...?   -  person Ilja Everilä    schedule 18.01.2017
comment
@ helo1987 Вы пробовали мой код? Я ответил на ваш вопрос?   -  person theodor    schedule 30.01.2017


Ответы (3)


поэтому я решил использовать текстовый запрос SQLalchemy следующим образом

params = {"id":1}
s = text("SELECT student.*, master_edu_level.name_level FROM student left join master_edu_level ON master_edu_level.id = student.edu_level_id WHERE student.id= :id")
users_query= session.execute(s, params ).fetchall()
results = schema.dump(users_query, many=True).data

а затем для схемы учащегося добавьте поля name_level

как это

class StudentSchema(Schema):
    not_blank = validate.Length(min=1, error='Field cannot be blank')
    id = fields.Integer(dump_only=True)
    student_name        = fields.String()  
    edu_level_id        = fields.String()  
    name_level = fields.String()

благодарю вас .

person helo1987    schedule 07.02.2017

На первом шаге измените схему таким образом:

import marshmallow as mm
from marshmallow_sqlalchemy import ModelSchema

class StudentSchema(ModelSchema):
    id = mm.fields.Integer(dump_only=True)
    student_name = mm.fields.String()
    education = mm.fields.Nested('MasterEdulevelSchema')

    class Meta:
        type_ = 'student'

    @mm.post_dump
    def format_dump(self, data):
        education = data.pop('education')
        data['education'] = education['name_level']
        return data


class MasterEdulevelSchema(ModelSchema):
    name_level = mm.fields.String()  

    class Meta:
        type_ = 'master_edu_level'

Он будет правильно форматировать ваши данные.

На следующем шаге объект базы данных дампа:

student_schema = StudentSchema() 
student = db.session.query(Student).join(MasterEduLevel, Student.edu_level_id == MasterEduLevel.id).first()
student_result = student_schema.dump(student)

Это должно работать, но я не проверял.

Кстати, есть много способов решить эту проблему. Как в случае с SQLAlchemy, так и на стороне Marshmallow.

person theodor    schedule 24.01.2017
comment
привет, извините, иоган, я опаздываю с вашим ответом, я следую вашим инструкциям, но получаю ошибку @marshmallow.post_dump NameError: name 'marshmallow' is not defined - person helo1987; 07.02.2017
comment
@ helo1987 вам нужно импортировать зефир вверху вашего файла import marshmallow ... - person theodor; 07.02.2017
comment
да .. я уже поставил импорт поверх из sqlalchemy.ext.declarative import declarative_base из marshmallow_jsonapi import Schema, поля из marshmallow import validate из marshmallow import ValidationError из sqlalchemy.exc import SQLAlchemyError из sqlalchemy.orm import отношения 'то же самое с примером сверху - person helo1987; 07.02.2017
comment
@ helo1987 все в порядке, но вы должны точно поставить import marshmallow. Я улучшил свой ответ, чтобы показать проблему импорта. Я также заменил Schema на ModelSchema, для которой требуется библиотека marshmallow_sqlalchemy. - person theodor; 07.02.2017

Попробуй это:

from app import db
from app import session
from sqlalchemy import Table, DateTime,Date, Text, text, Column, Integer, String, MetaData, ForeignKey, select, func
from sqlalchemy.ext.declarative import declarative_base
from marshmallow_jsonapi import Schema, fields
from marshmallow import validate
from marshmallow import ValidationError
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import relationship


class MasterEduLevel(db.Model):
    __tablename__ = 'master_edu_level'
    __table_args__ = {'extend_existing': True} 

    id = db.Column(Integer, primary_key=True, index=True)
    name_level = db.Column(String(20), nullable=False, index=True)


class MasterEdulevelSchema(Schema):
    not_blank = validate.Length(min=1, error='Field cannot be blank')
    id = fields.Integer(dump_only=True)
    name_level        = fields.String()  

    class Meta:
        type_ = 'master_edu_level'

class Student(db.Model):
    __tablename__ = 'student'

    id = db.Column(Integer, primary_key=True, index=True)
    student_name = db.Column(String(20), nullable=False, index=True)
    edu_level_id = db.Column(Integer, db.ForeignKey(MasterEduLevel.id))
    edu_level = db.relationship("MasterEduLevel")

class StudentSchema(Schema):
    not_blank = validate.Length(min=1, error='Field cannot be blank')
    id = fields.Integer(dump_only=True)
    student_name        = fields.String()  
    edu_level_id        = fields.String()

    edu_level           = fields.Function(lambda x: x.edu_level)  

    # You can use Nested for get the entire object of the MaterEduLevel (comment above edu_level)
    #edu_level           = fields.Nested("MasterEdulevelSchema")

    # You can also specify a field of the Nested object using the 'only' attribute (comment above edu_level)
    #edu_level           = fields.Nested("MasterEdulevelSchema", only=('name_level',))  

    class Meta:
        type_ = 'student'

student_schema = StudentSchema()
# You can also use the ONLY attribute here
#student_schema = StudentSchema(only=('student_name', 'edu_level'))

# Many results
users_query = session.query(Student).all()
results = student_schema.dump(users_query, many=True).data

# Many results with filter
users_query = session.query(Student).filter(Student.name.like('jo%')).all()
results = student_schema.dump(users_query, many=True).data

# Many results with filter in child property
users_query = session.query(Student).join(Student.edu_level).filter(MasterEduLevel.name == 'Bachelor').all()
results = student_schema.dump(users_query, many=True).data

# Just one row by PK
user = session.query(Student).get(1) #Student.id == 1
result = student_schema.dump(user).data
person Jair Perrut    schedule 02.03.2017
comment
Привет, @helo1987, это описано в документах, отношения SQLALchemy и Зефир - person Jair Perrut; 06.03.2017