Pregunta

Estoy tratando de agregar atributos a una relación de muchos a muchos en mi modelo, y ahora cuando carga un objeto, solo estoy obteniendo un objeto relacionado de mi consulta.

Específicamente estoy tratando de obtener todas las aplicaciones asociadas con una copia de seguridad dada, y también la columna BackupApp.Status.

Perdón por el info-volcado:

El código está aquí :

Sé que tengo cientos de relaciones para cargar:

$ sqlite3 dev.db "select count(*) from backups_apps where backup_id = 3 and app_id is not null;"
415

pero solo estoy obteniendo uno:

{
  "children": [
    {
      "children": [
        {
          "bundle_id": "com.iojoe.10", 
          "compressed": 13151750, 
          "name": "10", 
          "size": 14458882
        }
      ], 
      "name": "Games"
    }
  ], 
  "name": "root"
}

Los modelos:

# -*- coding: utf-8 -*-
from app_sizer.database import db, CRUDMixin, TimestampMixin, jsonify_plist

from sqlalchemy.ext.associationproxy import association_proxy

class App(db.Model, CRUDMixin, TimestampMixin):
    __tablename__ = 'apps'
    bundle_id = db.Column(db.String, unique=True, index=True)
    app_id = db.Column(db.Integer, unique=True, index=True)
    path = db.Column(db.String, unique=True, index=True)
    name = db.Column(db.String, index=True)
    main_genre = db.Column(db.String, index=True)
    compressed_size = db.Column(db.Integer)
    full_size = db.Column(db.Integer)
    plist = db.Column(db.PickleType)
    plist_json = db.Column(db.Text, default=jsonify_plist, onupdate=jsonify_plist)
    subgenre_1 = db.Column(db.String, index=True)
    subgenre_2 = db.Column(db.String, index=True)

    @classmethod
    def get_by_bundle_id(cls, bundle_id):
        return db.session.query(cls).filter(App.bundle_id == bundle_id).first()


    @classmethod
    def get_by_path(cls, path):
        return db.session.query(cls).filter(App.path == path).first()

    @classmethod
    def get_all(cls):
        return db.session.query(cls).all()

"""
class AppTag(CRUDMixin):
    app_id = db.Column(db.Integer, foreign_key='app.id')
    user_id = db.Column(db.Integer, foreign_key='user.id')
    tag = db.Column(db.String)
"""

# db.Index('idx_tag_user', 'app_tag.user_id', 'app_tag.tag')

class Backup(db.Model, CRUDMixin, TimestampMixin):
    __tablename__ = 'backups'
    path = db.Column(db.String, unique=True)
    name = db.Column(db.String)
    notes = db.Column(db.Text)
    # Springboard plist
    plist = db.Column(db.PickleType)
    plist_json = db.Column(db.Text, default=jsonify_plist, onupdate=jsonify_plist)
    @classmethod
    def get_by_path(cls, path):
        return db.session.query(Backup).filter(Backup.path == path).first()

    @classmethod
    def get_all(cls):
        return db.session.query(Backup).all()

# Why does this work but a declarative class doesn't?  No idea.
# http://xsnippet.org/359350/
# http://stackoverflow.com/q/5756559/25625
class BackupApp(db.Model, CRUDMixin):
    __tablename__ = 'backups_apps'
    backup_id = db.Column(db.Integer, db.ForeignKey('backups.id'), nullable=False, default=1)
    app_id = db.Column(db.Integer, db.ForeignKey('apps.id'), nullable=False, default=1)
    status = db.Column(db.String)

    app = db.relationship(App, backref="installed_apps")
    backup = db.relationship(Backup, backref="installed_apps")

    def __init__(self, app=None, backup=None, status=None):
        self.app = app
        self.backup = backup
        self.status = status

Backup.apps = association_proxy("installed_apps", "app")
App.backups = association_proxy("installed_apps", "backup")

La acción:

@blueprint.route("/backup/<int:backup_id>/apps.json")
def apps_json_for_backup(backup_id):
    print "in apps_json_for_backup({})".format(backup_id)
    backup = Backup.get_by_id(backup_id)
    root = to_treemap(backup.apps)
    return jsonify(root)


def to_treemap(apps):
    root = {"name": "root", "children": list()}
    genres = dict()
    for app in apps:
        if app.main_genre not in genres:
            genres[app.main_genre] = list()
        leaf = dict(name=app.name, size=app.full_size, compressed=app.compressed_size, bundle_id=app.bundle_id)
        genres[app.main_genre].append(leaf)
    for genre, leaves in genres.items():
        root['children'].append(dict(name=genre, children=leaves))
    return root

¿Fue útil?

Solución

OK, así que aquí está lo que pasó:

Cuando primero hice la tabla de copia de seguridad, no estaba usando crudmixin, por lo que no tenía una columna de identificación.Cuando migró la columna de identificación, todos los valores inicializados en 0. Sqlalchemy ignoró silenciosamente todas esas filas múltiples con la misma ID.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top