2014-11-18 7 views
2

내 응용 프로그램에는 런타임시에만 열 수를 알고있는 모델이 있습니다. 아래의 Factory과 같은 함수를 사용하여이 문제를 멋지게 해결할 수 있습니다.peewee : 동적으로 생성 된 모델 재사용

AttributeError: Foreign key: dynamictable.ref related name "dynamictable_set" 
collision with foreign key using same related_name. 

메시지는 매우 명확하고 나는 related_name 인수를 설정할 때 외래 키를 만들 때 : 내가 (잠재적으로 다양한 필드) 그것을 여러 번 사용하는 경우, 외부 키 ref의 생성에서 예외가 발생합니다 오류가 없습니다.

질문 :

  1. 가 왜이 같은 related_name 두 번째로 사용할 수 없습니다? StaticTable도 다시 정의해야합니까?

  2. 동적 모델을 사용하여 여러 데이터베이스에 쓰기 더 나은 방법이 있습니까?

최소, 재현 할 예 :

import peewee 

database_proxy = peewee.Proxy() 

class BaseModel(peewee.Model): 
    class Meta: 
     database = database_proxy 

class StaticTable(BaseModel): 
    foo = peewee.DoubleField() 

def Factory(fields): 
    class DynamicTable(BaseModel): 
     ref = peewee.ForeignKeyField(StaticTable) 
    for field in fields: 
     peewee.DoubleField().add_to_class(DynamicTable, field) 
    return DynamicTable 

def Test(fname, fields): 
    db = peewee.SqliteDatabase(fname) 
    database_proxy.initialize(db) 
    db.create_table(StaticTable) 
    dyntable = Factory(fields) 
    db.create_table(dyntable) 
    db.close() 


Test(':memory:', ['foo', 'bar']) 
Test(':memory:', ['foo', 'bar', 'extra']) 

답변

4

나는 이것이 당신이 명시 적으로 역 참조를 무시 할 수 있습니다 peewee의 버그를 강조 생각합니다. 나는 표를 열어 그것을 해결할 것이다. 한편

https://github.com/coleifer/peewee/issues/465

, 당신은 모델, 예를 들어,에 동적 related_name를 설정하여 오류를 침묵 수 있습니다

def Factory(fields): 
    dynamic_name = '_'.join(fields) 
    class DynamicTable(BaseModel): 
     ref = peewee.ForeignKeyField(StaticTable, related_name=dynamic_name) 
    for field in fields: 
     peewee.DoubleField().add_to_class(DynamicTable, field) 
     return DynamicTable 

업데이트 : # 465의 수정에 따라, 그것은 검증을 역 참조하지 않으려면 지금 가능 :

def Factory(fields): 
    class DynamicTable(BaseModel): 
     ref = peewee.ForeignKeyField(StaticTable, related_name=dynamic_name) 
     class Meta: 
      validate_backrefs = False 
    for field in fields: 
     peewee.DoubleField().add_to_class(DynamicTable, field) 
     return DynamicTable 
+0

빠른 답장을 보내 주셔서 감사합니다. 내 질문에 나는 일부 데이터베이스에 대해 동일한 필드가있을 수 있으므로 필드를 문자열에 조인하는 것이 고유하지 않음을 언급하는 것을 잊어 버렸다. 나는 해결 방법을 찾았지만, 나는 별도의 답변으로 게시 할 것이다. – hitzg

+0

확실히, 나는 단지 당신이 어떻게 주위를 둘러 쌀 수 있는지에 대한 예로서 그것을 제공했다. – coleifer

0

@coleifer의 (그의 대답에) 제안이만큼 잘 작동 필드 목록은 고유합니다. 필자의 경우에는 보장 할 수 없기 때문에 모든 모델 클래스가 공장에서 생성되는이 약간 더 복잡한 솔루션을 생각해 냈습니다.

import peewee 

database_proxy = peewee.Proxy() 

def orm_factory(): 

    class OrmWrapper: 
     class BaseModel(peewee.Model): 
      class Meta: 
       database = database_proxy 

     class StaticTable(BaseModel): 
      foo = peewee.DoubleField() 

     @classmethod 
     def dyntable_factory(cls,fields): 
      class DynamicTable(cls.BaseModel): 
       ref = peewee.ForeignKeyField(cls.StaticTable) 
      for field in fields: 
       peewee.DoubleField().add_to_class(DynamicTable, field) 
      return DynamicTable 

    return OrmWrapper 

def test(fname, fields): 
    orm = orm_factory() 
    db = peewee.SqliteDatabase(fname) 
    database_proxy.initialize(db) 
    db.create_table(orm.StaticTable) 
    dyntable = orm.dyntable_factory(fields) 
    db.create_table(dyntable) 
    db.close() 

test(':memory:', ['foo', 'bar']) 
test(':memory:', ['foo', 'bar']) 
관련 문제