raddevon
raddevon

Reputation: 3340

How can I create an entity in the GAE datastore of a type determined at runtime?

I have a URL route that captures the name of the model for which the entity will be created.(e.g. '/New<model>/') Now, I have the model name as a string. How can I take that string and use it to create a new entity of this model to put in the datastore?

I'm building a custom admin interface for GAE with the ability to register new models and have forms built dynamically based on registered models. I need a way to then be able to take the posted data submitted by the admin user and put it into the datastore using the correct model which will be in the URL the form is posted to. I'm currently building a handler to process requests coming into that URL scheme but have hit this roadblock. Any help is greatly appreciated.

Upvotes: 0

Views: 130

Answers (2)

raddevon
raddevon

Reputation: 3340

I didn't use globals to get at my class constructor. Instead, I made a variable that points to the current module and used getattr to capture my class constructor. Here's my handler in case anyone else wants to see what I did.

class NewThingHandler(BaseRequestHandler):
    def get(self, thing):
        self.redirect('/admin/')
    def post(self, thing):
        this_module = sys.modules[__name__]
        ThisModel = getattr(this_module, thing)
        arguments = {}
        for property in ThisModel.properties().keys():
            if type(ThisModel._properties[property]) is db.DateProperty:
                this_date = map(int, self.request.get(property).split('/'))
                this_date = datetime.date(this_date[2], this_date[0], this_date[1])
                arguments[property] = this_date
                continue
            arguments[property] = self.request.get(property)

        new_thing = ThisModel(**arguments)
        new_thing.put()
        self.redirect('/admin/')

thing is captured from the URL.

Upvotes: 0

unutbu
unutbu

Reputation: 879103

Although you could access the model class with

globals()[modelname]

if the model class is defined at the module level, as @TimHoffman points out in the comments, it is generally not a good idea to allow (potentially malicious) users arbitrary access to your globals.

Since you are generating model classes dynamically, a safer way would be to save those model classes in a dict:

model = { 'MyModel': MyModelClass, ... }

and then given the string name modelname, you could access the class with

model[modelname]

Upvotes: 0

Related Questions