2011-01-18 12 views
18

W Google App Engine istnieje coś takiego jak ListProperty, która pozwala na przechowywanie listy (tablicy) elementów. Możesz również określić typ zatrzymywanego przedmiotu, na przykład ciąg, liczbę całkowitą lub cokolwiek innego.Lista odnośników w Google App Engine dla Pythona

Google App Engine pozwala również na posiadanie właściwości Reference. ReferenceProperty "zawiera" odniesienie do innej jednostki modelu App Engine Google. Jeśli uzyskasz dostęp do ReferenceProperty, automatycznie pobierze on rzeczywistą encję, do której odnosi się odniesienie. Jest to wygodne, ponieważ bije o uzyskanie klucza, a następnie pozyskuje encję dla wspomnianego klucza.

Jednak nie widzę czegoś takiego jak ListReferenceProperty (lub ReferenceListProperty). Chciałbym przechowywać listę odniesień do innych podmiotów, które będą automatycznie rozwiązywane, gdy spróbuję uzyskać dostęp do elementów na liście. Najbliższe, jakie mogę uzyskać, to przytrzymanie listy obiektów db.Key. Mogę użyć tych kluczy, aby ręcznie pobrać powiązane z nimi jednostki z serwera.

Czy jest jakieś dobre rozwiązanie tego problemu? Zasadniczo chciałbym posiadać kolekcję odniesień do auto-dereferencji do innych podmiotów. Prawie mogę się tam dostać poprzez posiadanie klucza do innych podmiotów, ale chciałbym, aby "wiedział", że są to kluczowe przedmioty i że może je usunąć jako usługę dla mnie.

Dziękuję

Odpowiedz

13

Etap pierwszy:

Zastosowanie db.ListProperty (db.Key), aby utworzyć związek. Chcesz, aby ListProp był na Entity, który będzie miał mniej referencji w relacji Many to Many. To również da ci referencję. A więc:

class Spam 
    prop1 = db.String 
    eggs = db.List 

class Eggs 
    prop1 = db.string 
    @property 
    def spams(self): 
    return Spam.all().filter('eggs', self.key()) 

Zapewnia Referencje w obie strony.

Etap drugi:

stworzenie sposobu utlility że derefrences właściwości.

def prefetch_refprops(entities, *props): 
    """Dereference Reference Properties to reduce Gets. See: 
    http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine 
    """ 
    fields = [(entity, prop) for entity in entities for prop in props] 
    ref_keys = [prop.get_value_for_datastore(x) for x, prop in fields] 
    ref_entities = dict((x.key(), x) for x in db.get(set(ref_keys))) 
    for (entity, prop), ref_key in zip(fields, ref_keys): 
     prop.__set__(entity, ref_entities[ref_key]) 
    return entities 

Wykorzystanie byłoby:

derefrenced_spams = prefetch_refprops(Spams, models.Spam.eggs)  
+0

Stephen pan spróbować? Cały czas korzystam z tej metody i pierwotnie sugerowali ją ludzie, którzy spędzają wolny czas na IRC Google App Engine. –

+0

Przepraszam, dam to spróbować, jak tylko wyjdę z obecnej pętli iteracyjnej. Dziękuję za odpowiedź. –

+0

Tak, to jest coś. Chodzi mi o to, byłoby zgrabnie, gdyby to była faktyczna Właściwość, która zrozumiała, że ​​była to lista Referencji i wszystkich, ale nadal. To najlepsza odpowiedź, jaką do tej pory widziałem. –

6

Masz rację, nie ma wbudowany ReferenceListProperty. Byłoby możliwe napisanie go samemu - niestandardowe podklasy właściwości są zazwyczaj dość łatwe - ale poprawne wykonanie jest trudniejsze, niż mogłoby się wydawać, jeśli chodzi o usuwanie i buforowanie listy referencji.

Można jednak użyć opcji db.ListProperty(db.Key), która umożliwia zapisanie listy kluczy. Następnie można załadować je pojedynczo lub wszystkie jednocześnie, przy użyciu operacji wsadowej db.get(). Wymaga to samodzielnego wykonania kroku rozdzielczości, ale daje także większą kontrolę nad tym, kiedy usuniesz encje.