2015-01-07 22 views
6

Używam Flask i SQLAlchemy. Użyłem własnej abstrakcyjnej klasy bazowej i dziedziczenia. Kiedy próbuję użyć moich modeli w powłoce Pythona, pojawia się następujący błąd:Dziedziczenie SQLAlchemy nie działa

>>> from schedule.models import Task 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/home/teelf/projects/schedule/server/schedule/models.py", line 14, in <module> 
    class User(Base): 
    File "/home/teelf/projects/schedule/server/venv/lib/python3.4/site-packages/flask_sqlalchemy/__init__.py", line 536, in __init__ 
    DeclarativeMeta.__init__(self, name, bases, d) 
    File "/home/teelf/projects/schedule/server/venv/lib/python3.4/site-packages/sqlalchemy/ext/declarative/api.py", line 55, in __init__ 
    _as_declarative(cls, classname, cls.__dict__) 
    File "/home/teelf/projects/schedule/server/venv/lib/python3.4/site-packages/sqlalchemy/ext/declarative/base.py", line 254, in _as_declarative 
    **table_kw) 
    File "/home/teelf/projects/schedule/server/venv/lib/python3.4/site-packages/sqlalchemy/sql/schema.py", line 393, in __new__ 
    "existing Table object." % key) 
sqlalchemy.exc.InvalidRequestError: Table 'user' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns 
on an existing Table object. 

Jak to naprawić?

Kod:

manage.py:

#!/usr/bin/env python 

import os, sys 

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) 

from flask.ext.migrate import Migrate, MigrateCommand 
from flask.ext.script import Manager 

from server import create_app 
from database import db 


app = create_app("config") 

migrate = Migrate(app, db) 
manager = Manager(app) 

manager.add_command("db", MigrateCommand) 

if __name__ == "__main__": 
    manager.run() 

__init__.py:

from flask import Flask 

from flask.ext.login import LoginManager 

from database import db 
from api import api 
from server.schedule.controllers import mod_schedule 


def create_app(config): 
    # initialize Flask 
    app = Flask(__name__) 

    # load configuration file 
    app.config.from_object(config) 

    # initialize database 
    db.init_app(app) 

    api.init_app(app) 

    # initialize flask-login 
    login_manager = LoginManager(app) 

    # register blueprints 
    app.register_blueprint(mod_schedule) 

    return app 

database.py:

from flask.ext.sqlalchemy import SQLAlchemy 


db = SQLAlchemy() 

models.py:

from sqlalchemy.dialects.postgresql import UUID 

from database import db 


class Base(db.Model): 
    __abstract__ = True 

    id = db.Column(UUID, primary_key=True) 


class User(Base): 
    __tablename__ = "user" 

    username = db.Column(db.String) 
    password = db.Column(db.String) 
    first_name = db.Column(db.String) 
    last_name = db.Column(db.String) 
    authenticated = db.Column(db.Boolean, default=False) 

    def __init__(self, first_name, last_name, username): 
     self.first_name = first_name 
     self.last_name = last_name 
     self.username = username 

    def is_active(self): 
     """ All users are active """ 
     return True 

    def get_id(self): 
     return self.username 

    def is_authenticated(self): 
     return self.authenticated 

    def is_anonymous(self): 
     """ Anonymous users are not supported""" 
     return False 

controllers.py:

from flask import Blueprint 

from flask.ext.restful import reqparse, Resource 

from api import api 
from server.schedule.models import User 


mod_schedule = Blueprint("schedule", __name__, url_prefix="/schedule") 


class Task(Resource): 
    def put(self): 
     pass 

    def get(self): 
     pass 

    def delete(self): 
     pass 


api.add_resource(Task, "/tasks/<int:id>", endpoint="task") 
+1

Spróbuj usunąć '__mapper_args__', to nie ma sensu w Twojej przykład tak. – davidism

+0

@davidism To nie miało żadnego znaczenia. –

+0

Dwie rzeczy, które mogą być pomocne (chociaż nie miałem okazji ich przetestować): a) podczas inicjalizacji 'SQLAlchemy()' użyj swojej aplikacji Flask (np. 'Db = SQLAlchemy (app)'; b) 'users' jest [zarezerwowanym słowem kluczowym w PostgreSQL] (http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html), więc może '__tablename__ =" users "' może skończyć się jakimś konfliktem . – cuducos

Odpowiedz

12

spróbuj dodać

__table_args__ = {'extend_existing': True} 

do klasy User prawo unde r __tablename__=

okrzyki

+4

Skąd się tego nauczyłeś i czy możesz udostępniać dokumentację SQLalchemy, o której jest mowa w większej ilości? (Odpowiadasz właśnie to, czego potrzebowałem) –

+3

Chociaż jest to przydatne w niektórych przypadkach, ogólnie nie powinno to być potrzebne i jest znakiem, że definicje tabel są tworzone wiele razy - zazwyczaj przez przypadek. Rzucanie go jako generycznego "po prostu skopiuj i wklej to do twojego kodu" jest mylące i po prostu ukrywa prawdziwe błędy. –