0

에 액세스 할 수있는 가장 좋은 방법은 내가이 모델을했습니다NDB Jinja2의 KeyProperty

class Team(ndb.Model): 
    name = ndb.StringProperty() 
    password = ndb.StringProperty() 
    email = ndb.StringProperty() 


class Offer(ndb.Model): 
    team = ndb.KeyProperty(kind=Team) 
    cut = ndb.StringProperty() 
    price = ndb.IntegerProperty() 

class Call(ndb.Model): 
    name = ndb.StringProperty() 
    called_by = ndb.KeyProperty(kind=Team) 
    offers = ndb.KeyProperty(kind=Offer, repeated=True) 
    status = ndb.StringProperty(choices=['OPEN', 'CLOSED'], default="OPEN") 
    dt = ndb.DateTimeProperty(auto_now_add=True) 

나는이보기

class MainHandler(webapp2.RequestHandler): 
    def get(self): 
     calls_open = Call.query(Call.status == "OPEN").fetch() 
     calls_past = Call.query(Call.status == "CLOSED").fetch() 
     template_values = dict(open=calls_open, past=calls_past) 
     template = JINJA_ENVIRONMENT.get_template('templates/index.html') 
     self.response.write(template.render(template_values)) 

{% for call in open %} 
    <b>{{call.name}} {{call.called_by.get().name}}</b> 
    {% endfor %} 

이제이 작은 테스트 tempalte, 와를했습니다 get() 완벽하게 작동합니다.

내 질문 : 이 맞습니까? 더 좋은 방법은 없습니까? 개인적으로 나는 get() 템플릿의 값이 이상하다는 것을 알았고 뷰 내부에서 값을 가져오고 싶습니다.

  • 전화 calls_open의 모든 통화에 대해 to_dict() dict_call = call.to_dict()
  • 는 다음 dict_call dict_call['team'] = call.team.get().to_dict()
  • 개체를 추가 할당을 새 목록 res_open_calls=[]
  • 을 만듭니다

    내 생각은했다 목록에 res_open_calls.append(dict_call)

  • 다음이 방금 생성 된 목록을 반환합니다.

이것은 (수정 코드) 내가 쓴 요지 https://gist.github.com/esseti/0dc0f774e1155ac63797#file-call_offers_calls

더 깨끗 보이지만 약간 비싼 (제리스트가 생성되어야한다)이다. 거기에 더 나은/영리한 무언가가 있습니까?

+1

'호출'엔티티가 아니라 '팀'과 '오퍼'만 표시합니다. 나는보기에 템플릿이 아니라보기에 실제 논리가 있도록 기본 설정에 동의하지만 주어진 정보를 사용하면 도움이되지 않으므로 pls가 Q를 편집하여 전체 정보를 제공합니다. 감사합니다! –

+0

BTW, 아마도'Call' 엔티티에 의존하는 최상의 솔루션은 모델의 계산 된 속성 또는 인스턴스 메소드 일 수 있습니다. 이것은 다소 ndb 형식의 버크지만, 종종 내 개인적인 선호도입니다 :-) –

+0

@AlexMartelli 내 나쁜, 모델 및 내가 쓴 코드의 GIST를 추가하십시오. – EsseTi

답변

1

영업 이익이 명확하게 사용하고있는 것과 매우 다른 코드를 보여주고있다 : 그들이 그렇게 충돌한다 그것에 get을 요구하는 StringProperty으로 called_by을 보여, 그들이 보여주는 코드에 존재하지 않는 call.team에 대해 이야기. .. 어쨌든, 나는 그들이 실제로 가지고있는 것을 추측하려고 노력하고있다. 왜냐하면 나는 기본 아이디어가 중요하다는 것을 알기 때문이다.

OP, IMHO는 Jinjia2 템플릿에서 DB 작업을하는 것이 불편할 정도로 정확합니다. 이는 프레젠테이션 수준의 문제로만 제한됩니다. 내가 가정합니다 (추측!)가 Call 모델의 일부는 다음과 같습니다

class Call(ndb.Model): 
    team = ndb.KeyProperty(kind=Team) 

과 Jinja2의 관련 부분, 현재 OP 위해 일하고있다 :

{{{{call.team.get().name}} 

더 나은 구조 수도

class Call(ndb.Model): 
    team = ndb.KeyProperty(kind=Team) 
    @property 
    def team_name(self): 
     return self.team.get().name 

이며 템플릿은 단지 {{call.teamname}}입니다.

이것은 템플릿 확장 중에도 DB 연산을 수행하지만, 실제로는 Jinja2가 아닌 Python 코드 측에서 수행됩니다. 템플릿에서 모델의 데이터 아키텍처에 대한 자세한 내용을 구현하는 것보다 낫습니다. 발표에만 집중해야합니다.

또는, Call 인스턴스는 teamcache에게, name은, 하나는, 말하자면 수있는 ComputedProperty의 값은 변경되지 않습니다 거의 .put이며, 종종 표시하고있는 경우 : 그러나

class Call(ndb.Model): 
    team = ndb.KeyProperty(kind=Team) 
    def _team_name(self): 
     return self.team.get().name 
    team_name = ComputedProperty(self._team_name) 

를, 후자의 선택의 여지가 없다 (더 많은 저장 공간을 필요로하고 실행 시간을 절약하지 못하고 데이터 저장소와의 실제 상호 작용을 복잡하게 함) Call 엔티티에 대한 일부 쿼리도 team_name에 쿼리해야합니다 해야한다).

일이 대안을 선택 않은 경우 Jinjia2 템플릿 것 여전히 사용 {{call.teamname}}이는 엄격하게 프리젠 테이션에 연결 템플릿에만 논리에 사용하는 것이 가장 좋습니다 이유에서 힌트 - 그것은 속성과 특성을 구현하기위한 더 많은 자유도를 잎 파이썬 코드 측면에서, 템플릿을 변경할 필요가 없습니다. "관심의 분리"는 프로그래밍의 훌륭한 원칙입니다. 오히려, 이중 간접를 call.offersoffer.team를 통해 - Call 참으로 표시하지만 물론 문제의 반복과 같이 더 call.team가 없습니다

다른 곳에서 게시 한 조각이 합병증의 높은 수준을 제안한다. 이는 엔티티 관계 모델링 측면에서 의미가 있지만 GAE의 데이터 저장소를 포함하여 모든 NoSQL 데이터베이스에서 스 니펫이 제안하는 본질적으로 "표준화 된"용어로 구현할 수 있습니다.

팀이 이름을 변경하지 않으며, 호출 를 비정규 화에 더 나은 성능을 표시 할 수 있습니다, 이벤트의 자신의 목록을 변경하지 않으면 Call에서 기술적으로 중복 정보를 저장하는 모델 (스 니펫에서, 페치 것을) 이중 간접 통해 실행 - Call 기관에 Offer 객체의 사본을 포함, 구조 특성, https://cloud.google.com/appengine/docs/python/ndb/properties#structured에 의해 예, 그리고 Offer 법인의 경우 a Team 객체의 복사본 (또는 심지어 그냥 팀의 이름) .

모든 비정규 화와 마찬가지로 데이터 저장소에서 엔티티 당 몇 바이트의 추가 바이트가 필요할 수 있지만 그럼에도 불구하고 fetch 시간에 필요한 데이터 저장소 액세스 수를 최소화하여 비용을 충분히 지불 할 수 있습니다. 다양한 엔티티 및 속성

그러나 지금까지 우리는 템플릿에서 무엇을 넣어야할지, 파이썬 측에서 무엇을 할 것인가에 관한 질문에서 멀리 벗어났습니다. 데이터 저장소 패턴을 최적화하는 것은 자체 Q의 가치가있는 별도의 문제입니다.

로직 거주지로 템플릿 대 파이썬 코드의 후반, 핵심 문제에 대한 내 입장을 요약 : 파이썬 코드 측에 있어야 데이터 액세스 로직, 이상적으로 적시에 액세스 할 수 property를 사용 Model 클래스 (에 포함 엔티티 구축시 또는 엔티티 종료시에 비정규 화하는 모든 방법). Jinjia2 템플릿 (또는 다른 종류의 순수한 프리젠 테이션 계층)은 데이터 액세스 (물론 비즈니스 논리도 아님)가 아닌 프리젠 테이션에 직접 필요한 논리 만 가져야합니다.

+0

코드에 좋지 않습니다. 잘못 입력했습니다. 이 대답은 놀랍습니다. 데이터베이스를 만드는 더 좋은 전략에 대한 정보는 어디에서 찾을 수 있습니까? 나는이 전략을 꽤 자주 사용했기 때문에 분리 된 테이블, 반복 된 키 또는 관계에 대해 반복되는 structuredProperty를 사용해야 할 때가 아직 명확하지 않습니다. – EsseTi

+1

@EsseTi, 나는 Dan Sanderson의 연구가 항상 유익하다는 것을 발견했습니다. 그의 블로그는 http://ae-book.appspot.com/에 있으며, Early Release에서 사용할 수있는 그의 책 (GAE Python과 GAE Java에 대한 두 가지 별도의 책)과 최신판 (4 월 인쇄판)이 블로그로 있습니다. 언급. (면책 조항 : 나는 그가 동료이기 때문에 편향 될 수 있으며 우리는 같은 출판사를 위해 글을 쓸 수는 있지만, 나는 그를 개인적으로 모릅니다.) –