2014-10-28 16 views
6

Điều này liên quan đến câu hỏi này converting to declarative method and column property, chưa bao giờ được trả lời.SQLAlchemy Cách ánh xạ cột đơn của mối quan hệ một-một bằng cách khai báo

Chúng tôi đang cố gắng thiết lập dự án Flask-SQLAlchemy trên lược đồ hiện có (chúng tôi không thể thay đổi) và quyết định cú pháp khai báo để chúng tôi có thể sắp xếp các lớp thành nhiều tệp theo cách lành mạnh để bảo trì. Điều này làm việc cho hầu hết các mối quan hệ của chúng tôi ngoại trừ một cái gì đó mà chúng ta gọi, vì thiếu một thuật ngữ tốt hơn, các bảng thuộc tính. Đây là các bảng lá một-một trong một số đối tượng chính, và thường chứa một số từ vựng được kiểm soát cho thuộc tính. Mục tiêu trong ORM là ánh xạ tất cả các (trong đó có rất nhiều) các loại bảng như thể chúng là các thuộc tính của bảng chính.

Dưới đây là một ví dụ SQA với hai bảng:

class MarkerType(db.Model): 
    __tablename__="mrk_types" 
    _marker_type_key = db.Column(db.Integer,primary_key=True) 
    name = db.Column(db.String()) 

class Marker(db.Model): 
    __tablename__="mrk_marker" 
    _marker_key=db.Column(db.Integer,primary_key=True) 
    _marker_type_key=db.Column(db.Integer()) 

Chúng tôi muốn truy cập MarkerType.name như thể chúng ta đang nói Marker.markertype, hoặc trong một truy vấn như Marker.markertype == 'điều'. Cách duy nhất tôi có thể quản lý đó là với một column_property trong lớp Marker, như vậy:

markertype = db.column_property(
      db.select([MarkerType.name]). 
      where(MarkerType._marker_type_key==_marker_type_key) 
    ) 

Tuy nhiên, tôi dường như không thể tìm thấy làm thế nào để thực hiện điều này một cách tường thuật, và có lẽ như vậy không tồn tại. Có cách nào lành mạnh để tôi có thể đạt được điều này mà không phải lo lắng về việc nhập khẩu của tôi hay thậm chí tệ hơn thứ tự các lớp học của tôi? Vì chúng tôi có hàng trăm bảng để lập bản đồ, tôi có thể thấy đây là một cơn ác mộng bảo trì nếu chúng ta phải lo lắng về thứ tự lớp và thứ tự nhập.

Nếu tất cả điều này là hoàn toàn không thể, hãy suy nghĩ mơ ước, cách tiếp cận tốt hơn để lập bản đồ các bảng này là gì?

+0

Bạn đã xem [Lập bản đồ thuộc tính dọc '] (http://docs.sqlalchemy.org/en/rel_0_9/orm/examples.html#module-examples.vertical) ví dụ? – van

+0

Không, nhưng tôi không chắc chắn tình trạng của tôi có được áp dụng hay không. Tôi không có một bảng con với các cặp khóa giá trị. Đó là một bảng con chỉ với một giá trị. Tôi không chắc liệu điều đó vẫn được coi là một bảng thẳng đứng hay không. Ngoài ra, các ví dụ cho việc thiết lập assocation_proxy không nhìn khai báo. – kevinrstone

Trả lời

1

này nghe có vẻ giống như một trường hợp sử dụng tuyệt vời cho Association Proxy. Proxy này là một trường của một mô hình liên quan. Trong trường hợp này việc thực hiện sẽ là:

from sqlalchemy.orm import relationship 
from sqlalchemy.ext.associationproxy import association_proxy 

class MarkerType(db.Model): 
    __tablename__="mrk_types" 
    _marker_type_key = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String()) 

class Marker(db.Model): 
    __tablename__="mrk_marker" 
    _marker_key=db.Column(db.Integer,primary_key=True) 
    _marker_type_key=db.Column(db.Integer, ForeignKey('mrk_types._marker_type_key') 

    mt = relationship(MarkerType, uselist=False) 
    marker_type = association_proxy('mt', 'name') 

này cho phép truy vấn như session.query(Marker).filter_by(marker_type='my_marker_type')

Trường marker_type là một proxy của trường name trên đối tượng MarkerType. Đối tượng đó có thể được tham chiếu bởi trường mt (trường mối quan hệ)

Lưu ý uselist=False. Điều này cho biết mỗi Marker có 1 loại đánh dấu. Mối quan hệ tự động phát hiện ForeignKey và sử dụng nó.

+0

Vâng, điều này có vẻ chính xác những gì tôi cần. Cảm ơn. – kevinrstone

1

Vì vậy, từ những gì tôi thu thập, bạn bị mắc kẹt với hai bảng. Một với một số nguyên col, một với một chuỗi col.

Class Marker 
    _marker_key_ primary_key 
    # _ = Integer ## This can be ignored as its unnecessary. 

Các khác có

Class MarkerType 
    _marker_type_key = primary_key 
    name = String 

Như tôi đã đọc nó, bạn muốn Lớp Marker để có nhiều chuỗi Lớp MarkerType mà bạn có thể dễ dàng thao tác hoặc kêu gọi. Mặc dù, tôi không thực sự chắc chắn nếu đó là những gì bạn muốn.

Nếu có, bạn có thể đạt được điều này giả sử bạn kiểm soát việc tạo cơ sở dữ liệu. Bạn có thể xây dựng cờ ở đầu mỗi tên trỏ đến khóa chính Đánh dấu.

Ví dụ: MarkerType.name = 10324_Orange

Tôi không quen thuộc trong việc sử dụng SQLAlchemy mà không phiên, và không thực sự cảm thấy thích làm nghiên cứu, vì vậy tôi chỉ sẽ viết câu trả lời của tôi giả sử bạn đang sử dụng SQLAlchemy phiên, vì vậy bạn có thể có được khái niệm và có thể điều chỉnh khi cần.

### !!! ASSUME 'create_session' method exists that 
#### creates a sqlalchemy session instance 

Class Marker: 
    # ... initialize and such 
    # ... then add these helper methods 

    ## Get all properties linked to this primary table row 
    def marker_types(): 
     return db.query(MarkerType). 
      filter(MarkerType.name.like(str(self._marker_key_)+"_%")).all() 
    ## Get specific property linked to this primary table row 
    def marker_type(marker_type_name): 
     db = create_session() 
     marker_type_list = db.query(MarkerType). 
      filter(MarkerType.name.like(str(self._marker_key_)+"_%") 
      AND marker_type_name == MarkerType.name).first() 
     db.close() 
     return marker_type_list 

    def update_marker_type(old_val, new_val) 
     db = create_session() 
     updated_marker_type = marker_type(old_val) 
     updated_marker_type.name = str(self._marker_key_)+" "+new_val 
     db.close() 
     return True 

    def create_marker_type(val) 
     marker_type = MarkerType(name = str(self._marker_key_)+" "+val) 
     db = create_session() 
     db.add(marker_type) 
     db.commit() 
     db.close() 
     return marker_type._marker_type_key 

Từ đây bạn có thể thêm các cờ bổ sung vào chuỗi tên. Những thứ như loại thuộc tính.

Marker.id = 193 

MarkerType.id = 1 
MarkerType.name = "193_color_Black" 
MarkerType.id = 2 
MarkerType.name = "193_style_Fine" 

cờ bổ sung này có thể cho phép bạn tìm kiếm các thuộc tính chung tên cụ thể liên quan đến hàng cụ thể của bạn, và bao la hơn sử dụng được, mặc dù hơi phức tạp hơn. Thực sự phụ thuộc vào trường hợp sử dụng của bạn.

+0

Đã lâu rồi, nhưng tôi chưa bao giờ thực sự giải quyết vấn đề này. Xin lỗi, câu trả lời của bạn không phải là những gì tôi đang tìm kiếm. Tôi thực sự muốn có cách xác định cột_property như tôi đã trình bày, nhưng với cú pháp chuỗi nên tôi không phải nhập lớp MarkerType. Bạn có thể làm điều này với các mối quan hệ và một số thứ khác. – kevinrstone

+0

Không phải lo lắng .. có ai đó đã đặt một khoản tiền thưởng vào nó, vì vậy tôi đã tìm ra id thử một cái gì đó. Không chính xác rõ ràng về những gì bạn đang tìm kiếm, nhưng tìm id cho nó một đi trên bảng liên kết không chính thức. – ExperimentsWithCode

+0

Btw tôi không nghĩ rằng bạn cần phải nhập khẩu markertype nếu một nguồn tài nguyên của điểm đánh dấu, và nhập khẩu nơi mà lớp đó được xác định. Đặc biệt nếu bạn chỉ tương tác với nó thông qua các phương thức được xây dựng trong lớp đánh dấu của bạn. – ExperimentsWithCode

1

Sử dụng relationship để cho phép truy cập vào marker_type từ bảng Marker và chỉ định ràng buộc ForeignKey để SQLAlchemy hiểu mối quan hệ giữa các bảng.

Điều này cho phép bạn dễ dàng truy cập thuộc tính MarkerType từ bản ghi Marker cũng như truy vấn MarkerType.name. Sau đây cho thấy chèn hai bản ghi và sau đó lọc dựa trên thuộc tính name.

>>> db.session.add(Marker(marker_type=MarkerType(name="blue"))) 
>>> db.session.add(Marker(marker_type=MarkerType(name="red"))) 
>>> db.session.commit() 


>>> markers = Marker.query.all() 
>>> print({m._marker_key: m.marker_type.name for m in markers}) 

{1: 'blue', 2: 'red'} 

>>> result = Marker.query.filter(Marker._marker_type_key==MarkerType._marker_type_key) \ 
...      .filter(MarkerType.name=='blue').all() 
>>> print({m._marker_key: m.marker_type.name for m in result}) 

{1: 'blue'} 

Trình tự khai báo của lớp không không vật chất và các lớp học cần không được khai báo với nhau. Tuy nhiên, lược đồ phải được đăng ký với cùng một thể hiện của db và khi bạn truy vấn đối với các bảng, các lớp bảng mà bạn tham chiếu sẽ cần phải được nhập.

Sau khi thêm relationshipForeignKey để đánh dấu các lược đồ tường thuật sẽ trở thành:

class MarkerType(db.Model): 
    __tablename__="mrk_types" 
    _marker_type_key = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String()) 

class Marker(db.Model): 
    __tablename__="mrk_marker" 
    _marker_key=db.Column(db.Integer, primary_key=True) 
    _marker_type_key=db.Column(db.Integer(), db.ForeignKey('mrk_types._marker_type_key')) 
    marker_type=db.relationship('MarkerType') 
+0

Tuy nhiên, điều này không cho phép truy vấn loại điểm đánh dấu dưới dạng chuỗi trực tiếp, như được trình bày bởi OP –

+0

@JesseBakker thực sự tôi tin điều đó. Tôi đã thêm một ví dụ. – user650881

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