2013-03-27 22 views
8

mô hình User tôi làAlembic: Cách di chuyển loại tùy chỉnh trong mô hình?

class User(UserMixin, db.Model): 
    __tablename__ = 'users' 
    # noinspection PyShadowingBuiltins 
    uuid = Column('uuid', GUID(), default=uuid.uuid4, primary_key=True, 
        unique=True) 
    email = Column('email', String, nullable=False, unique=True) 
    _password = Column('password', String, nullable=False) 
    created_on = Column('created_on', sa.types.DateTime(timezone=True), 
         default=datetime.utcnow()) 
    last_login = Column('last_login', sa.types.DateTime(timezone=True), 
         onupdate=datetime.utcnow()) 

nơi GUID là một kiểu tùy chỉnh như mô tả trong sqlalchemy docs (Chính xác giống nhau)

Bây giờ khi tôi chạy

alembic revision --autogenerate -m "Added initial table" 

tôi nhận được của tôi upgrade() như

def upgrade(): 
    ### commands auto generated by Alembic - please adjust! ### 
    op.create_table('users', 
    sa.Column('uuid', sa.GUID(), nullable=False), 
    sa.Column('email', sa.String(), nullable=False), 
    sa.Column('password', sa.String(), nullable=False), 
    sa.Column('created_on', sa.DateTime(timezone=True), nullable=True), 
    sa.Column('last_login', sa.DateTime(timezone=True), nullable=True), 
    sa.PrimaryKeyConstraint('uuid'), 
    sa.UniqueConstraint('email'), 
    sa.UniqueConstraint('uuid') 
    ) 
    ### end Alembic commands ### 

nhưng trong quá trình áp dụng nâng cấp ->alembic upgrade head, tôi thấy

File "alembic/versions/49cc74d0da9d_added_initial_table.py", line 20, in upgrade 
    sa.Column('uuid', sa.GUID(), nullable=False), 
AttributeError: 'module' object has no attribute 'GUID' 

Làm thế nào tôi có thể làm cho nó hoạt động với GUID/tùy chỉnh gõ vào đây?

Trả lời

7

Bạn có thể thay thế sa.GUID() bằng sa.CHAR(32) hoặc UUID() (sau khi thêm dòng nhập from sqlalchemy.dialects.postgresql import UUID) tùy thuộc vào phương ngữ.

Thay thế bằng GUID() (sau khi thêm dòng nhập from your.models.custom_types import GUID) cũng sẽ hoạt động, nhưng sau đó tập lệnh nâng cấp được gắn với mã mô hình của bạn, điều này có thể không tốt.

+0

nhưng điều đó sẽ phá vỡ trong các thử nghiệm nếu tôi đang sử dụng 'sqlite' cộng với nó sẽ không nhất quán, phải không? – daydreamer

+1

Tôi thực sự không quan tâm nhiều đến việc sử dụng 'sqlite' trong các thử nghiệm, vì môi trường thử nghiệm phải theo sát chặt chẽ việc sản xuất. Ngoài ra, bạn có đang triển khai cùng một mã chống lại nhiều hơn một phương ngữ không? – sayap

+0

Dù sao, tôi sẽ muốn các tập lệnh di chuyển nhất quán với lược đồ thực tế tại thời điểm, tính nhất quán với mã sẽ bị chết vì mã này sẽ thay đổi vĩnh viễn. – sayap

3

Tôi đã có một vấn đề tương tự và giải quyết nó như sau:

Giả sử bạn có các module sau my_guid, chứa (từ trang web mà bạn đã trích dẫn, với những thay đổi đặt tên nhỏ):

import uuid as uuid_package 
from sqlalchemy.dialects.postgresql import UUID as PG_UUID 
from sqlalchemy import TypeDecorator, CHAR 

class GUID(TypeDecorator): 
    impl = CHAR 

    def load_dialect_impl(self, dialect): 
     if dialect.name == 'postgresql': 
      return dialect.type_descriptor(PG_UUID()) 
     else: 
      return dialect.type_descriptor(CHAR(32)) 

    def process_bind_param(self, value, dialect): 
     if value is None: 
      return value 
     elif dialect.name == 'postgresql': 
      return str(value) 
     else: 
      if not isinstance(value, uuid_package.UUID): 
       return "%.32x" % uuid_package.UUID(value) 
      else: 
       # hexstring 
       return "%.32x" % value 

    def process_result_value(self, value, dialect): 
     if value is None: 
      return value 
     else: 
      return uuid_package.UUID(value) 

Nếu bạn sử dụng GUID này trong các mô hình của mình, bạn chỉ cần thêm ba dòng tại alembic/env.py:

from my_guid import GUID 
import sqlalchemy as sa 
sa.GUID = GUID 

Điều đó hiệu quả đối với tôi. Hy vọng rằng sẽ giúp!

+1

Làm việc cho tôi. Cảm ơn. – Soferio

+0

Thứ hai - điều này làm việc cho tôi trong khi nhiều câu trả lời khác về câu hỏi này và các câu hỏi khác thì không. Cảm ơn! –

1

Sử dụng chức năng __repr__ của lớp impl thuộc tính làm việc cho tôi đối với hầu hết các loại tùy chỉnh. Tôi tìm thấy nó sạch hơn để có định nghĩa di chuyển chứa bên trong lớp thay vì lo lắng về việc nhập khẩu trong env.py hoặc scripts.py.mako của bạn. Thêm vào đó, nó giúp bạn dễ dàng di chuyển mã của bạn giữa các mô-đun.

Class GUID(types.TypeDecorator) 
    impl = CHAR 

    def __repr__(self): 
     return self.impl.__repr__() 

    # You type logic here. 

Việc di chuyển sẽ sản xuất CHAR(length=XXX).

Các vấn đề liên quan