0

I am using mongoengine in python as an ORM. Now I have a situation where I have a class, actually the a model, of the form:

from mongoengine import *
class SomeDetails(Document):
    alias = StringField(required=True)
    version = StringField(required=True)
    author = StringField(required=True)
    someName = StringField(required=True)

Now I need to create the object of this class (and hence a document at runtime)

I can create an object of a normal class at runtime by using inspection, something like this:

from inspect import isclass
# moduleImport is a method made to facilitate importing of modules at runtime.
new_module = moduleImport('myModule')
classes = [x for x in dir(new_module) if isclass(getattr(new_module, x))]
class_object = getattr(new_module, classes[0])
instance = class_object()

And the above works perfectly. I am able to create an object at runtime and then use it as I wish.

However, in the former case above, when I need to create an object (or actually a mongo document in this case), as per the mongoengine documentation here and here, I need to create the object something like this:

docObject = SomeDetails(alias=value, version=value, author=value, someName=value)
docObject.save() # to save the document in the mongodb

wherein I need to specify the values for each of the keyword arguments while creating the object of the class, so that the document gets saved successfully.

So in this case, if I try creating the object of the SomeDetails class at runtime (as shown in the inspect example above) how can I provide these keyword arguments at the runtime while creating the object?

An important catch

So the keyword arguments are also not known before hand. They too are fetched at runtime. At runtime, before object creation, yes, I do know the list of keyword args and it's values, which is available to me as a dictionary as :

{alias:"a", version:"b", author:"c", someName:"d"}

but even then, this dic itself is available only at runtime.

qre0ct
  • 5,680
  • 10
  • 50
  • 86
  • 1
    Honestly, you seem to be having to do a lot of code gymnastics here because your data is dynamically structured. Although mongodb is great at dealing with that, mongoengine is really not. You may want to consider simply using pymongo – Steve Rossiter Apr 05 '17 at 11:01

2 Answers2

1

You can try this:

data = {alias:"a", version:"b", author:"c", someName:"d"}
instance = class_object(**data)

More on **kwargs here

Steve Rossiter
  • 2,624
  • 21
  • 29
0

Presumably, you would just replace the line

instance = class_object()

With

instance = class_object(alias="a", version="b", author="c", someName="d")

If this doesn't work, please elaborate on what error you get.

Trevor Merrifield
  • 4,541
  • 2
  • 21
  • 24
  • Yes. This would definitely work. However, there is a small catch. My bad didn't call it out in the question. So the keyword arguments are also not known before hand. They too are fetched at runtime. So the above suggestion does not work in this case, as I do not have this info until runtime. At runtime, before object creation, yes, I do know the list of keyword args and it's values, which is available to me as a dictionary as : {alias:"a", version:"b", author:"c", someName:"d"}, but even then, this dic itself is available only at runtime. Updated the question as well. – qre0ct Apr 05 '17 at 06:52
  • You can infer steve's answer from mine if you know that any expression can be passed as an argument to a function. That is, if you can call `f("ab")` then you can call `f("a" + "b")` or you could set a variable `myvar="ab"` then call `f(myvar)`, and get the exact same result. I think this question really stems from a misunderstanding about how python evaluates code. There is no distinction between passing a hard coded string to a function, performing variable lookups, or expanding a dictionary, regardless it's going to be done at run time by evaluating an expression. – Trevor Merrifield Apr 09 '17 at 22:02