Datastore list of lists

2020-07-27 05:00发布

问题:

I need to make a list property that will contain lists, something like: db.ListProperty(list(str))

I know list(str) is not a supported value type so as I imagined I received a "ValueError" exception. Thought maybe there is a creative idea out there of how to overcome this :)

Thanks!

回答1:

You could use pickle to serialize your list and store it in a BlobProperty field.



回答2:

Expanding on Adam's suggestion, you can push the pickling into its own Property class. Here is an example that handles validation, and converting the provided list into and out of a Blob type. The provided list can contain any data type or combination of datatypes, since it just stores a standard python list.

import pickle

class GenericListProperty(db.Property):
  data_type = db.Blob

  def validate(self, value):
    if type(value) is not list:
      raise db.BadValueError('Property %s must be a list, not %s.' % (self.name, type(value), value))
    return value

  def get_value_for_datastore(self, model_instance):
    return db.Blob(pickle.dumps(getattr(model_instance,self.name)))

  def make_value_from_datastore(self, value):
    return pickle.loads(value)

You use it as you would any other property.

class ModelWithAGenericList(db.Model):
  mylist = GenericListProperty()

class MainHandler(webapp.RequestHandler):
  def get(self):
    db.delete(ModelWithAGenericList.all())

    m = ModelWithAGenericList(mylist = [[1,2,3],[4,5,6],6])
    m.put()

    m = ModelWithAGenericList.all().fetch(1)[0]
    self.response.out.write(str(m.mylist))
    # Outputs: [[1, 2, 3], [4, 5, 6], 6]


回答3:

If your using Java you could store the list of lists as a blob (provided they are standard lists and their contents are serializable) but this does stop you being able to get datastore to searches on its contents.

// -----------------------------------------------
import java.io.Serializable;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import com.google.appengine.api.datastore.Blob;

Serializable s = (Serializable) myListOfLists;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(s);
    oos.close();
}catch(IOException ioexception){

}
entity.setProperty("data", new Blob(baos.toByteArray()));

// -------------------------------------------

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import com.google.appengine.api.datastore.Blob;

ByteArrayInputStream bais = new ByteArrayInputStream(((Blob)e.getProperty("data")).getBytes());
try {
    ObjectInputStream ois = new ObjectInputStream(bais);
    myListOfLists = (List<List<String>>) ois.readObject();
} catch (IOException e1) {

} catch (ClassNotFoundException e1) {

}