8

Czy istnieje dobry sposób na przechowywanie słownika Python w magazynie danych? Chcę zrobić coś takiego:Jak umieścić słownik w magazynie danych?

from google.appengine.ext import db 

class Recipe(db.Model): 
    name = db.StringProperty() 
    style = db.StringProperty() 
    yeast = db.StringProperty() 
    hops = db.ListofDictionariesProperty() 

Oczywiście ta ostatnia linia w rzeczywistości nie działa. Potrzebuję przeskoków do listy par klucz-wartość, gdzie klucz jest zawsze łańcuchem, a wartość może być ciągiem, int lub float, ale nie widzę niczego, co pozwoliłoby mi na to w Property classes.

Odpowiedz

7

Serializowanie dykcji za pomocą repr to dobry sposób na zrobienie tego. Możesz następnie odtworzyć go za pomocą eval lub, jeśli nie ufasz danym, "safe eval".

Zaletą repr w procesie trawienia jest to, że dane można odczytać w bazie danych, nawet w rozpaczliwych przypadkach.

+1

JSON jest generalnie bezpieczniejsze niż eval. –

+0

Prawdopodobnie nie będę musiał sprawdzać tego pola, ale podoba mi się, że mam opcję. Także, popraw mnie, jeśli się mylę, ale czy używanie repr i używanie JSON nie ma takiego samego wyjścia w tym przypadku? –

+0

Nawet z "bezpieczną ewaldą", 'repr' może być niebezpieczne. Sam Guido wątpi, że mógłbyś napisać taką funkcję. Zobacz http://code.google.com/p/googleappengine/issues/detail?id=671. JSON jest prostszy od Pythona i mam więcej pewności, że parser JSON nie byłby podatny na zagrożenia w sposób, w jaki "eval" może być. – lemnar

2

Można użyć słownika pickle i zapisać jako StringProperty.

2

Jestem prawie pewien, że nie ma sposobu na przechowywanie słownika Python. Ale dlaczego nie po prostu umieścić w chmielu to, co chcesz, jako drugi model?

Również, jak wspomniano przez Johna, można użyć marynaty, ale (i popraw mnie, jeśli się mylę) przechowuję ją jako wartość Blob.

+1

@Bartek, możesz używać funkcji zrzutu i ładunków modułu pikle do pracy z ciągami: >>> cPickle.loads (cPickle.dumps ({1: "one"})) {1: 'jeden'} – Mark

1

Twoje opcje to używanie pikle, używanie db.Expando i przypisywanie każdemu kluczowi w dykcie oddzielnej właściwości lub posiadanie StringListProperty kluczy i jednej z wartości oraz zip() z powrotem do dyktatury, gdy czytanie.

7

Można użyć JSON

+0

+1: Reguły JSON. –

+1

@gnibbler: Konwertuj 'dict' na format JSON i zachowaj go jako' db.StringProperty'? – Kit

+0

@Kit, tak. Oprócz bycia bezpieczniejszym niż repr/eval i zaoszczędzenia na pisaniu "bezpiecznej ewaluacji", JSON jest bardziej przenośny, jeśli na pewnym etapie używasz innego języka –

0

zrobiłem to tak:

class MyEntity(db.Model): 
    dictionary_string = db.StringProperty() 

payload = {{}...{}} 

# Store dict 
my_entity = MyEntity(key_name=your_key_here) 
my_entity.dictionary_string = str(payload) 
my_entity.put() 

# Get dict 
import ast 
my_entity_k = db.Key.from_path('MyEntity', your_key_here) 
my_entity = db.get(my_entity_k) 
payload = ast.literal_eval(my_entity.dictionary_string)