Mongoengine: Querying the database from inside Document - python

I have a class with a reference field on itself, because some users in my app can have sub users that are kinda like employees. I defined my Document this way:
class User(Document):
__parent = ReferenceField('self', db_field='parent')
I tried to define a property inside my User model to retrieve the parent from inside the class but I haven't managed to make it work. I've read the documentation on Default Document Queries and have tried using queryset_manager decorator and then calling that function from my property but when I try that I get an error saying that 'QuerySetManager is not callable'.
Basically what I want to do is making the property return a User instance containing the parent of the child that is calling. I hope this can help visualize it.
#property
def get_parent(self):
return self.objects(id=self.__parent).get()

Related

Accessing "self" in save method of class-based model

I have two models that look like this:
class ModelOne(models.Model):
foo = models.CharField(max_length=25)
def save(self,*args,**kwargs):
a = ModelTwo.objects.get(pk=arbitrary_pk)
a.somefield.add(self) # I am worried about this line here
super(ModelOne,self).save(*args,**kwargs)
class ModelTwo(models.Model):
somefield = models.ManyToManyField(ModelOne)
The line where I am adding self to a.somefield is the line I am worried about. How can I do this without error? Currently, I am getting:
ValueError: Cannot add "<ModelOne>": the value for field "modelone" is None
Thanks in advance
You can't do that because when you call .add() you have yet to save your model. That means that the model may not have been created (so it doesn't have an ID yet).
Basically you're telling Django to update the Foreign Key with something that doesn't exist yet (NULL), which will error out. You need to make sure the model has been created before you can set the foreign key.
try moving the a.somefield.add(self) to AFTER the super() call.
You cannot save many to may field before calling actual save method, you modify code like,
def save(self,*args,**kwargs):
super(ModelOne,self).save(*args,**kwargs) # Here your self has been saved
a = ModelTwo.objects.get(pk=arbitrary_pk)
a.somefield.add(self) # Now your self can be add as ManyToMany as it is already saved in db
I hope this help.
Add the instance to the many to many field after calling the save method.
class ModelOne(models.Model):
foo = models.CharField(max_length=25)
def save(self,*args,**kwargs):
super(ModelOne,self).save(*args,**kwargs)
a = ModelTwo.objects.get(pk=arbitrary_pk)
a.somefield.add(self) #add self to the object manytomany.
a.save() #save the object.
class ModelTwo(models.Model):
somefield = models.ManyToManyField(ModelOne)
You need to save the self object first. The many to many relation needs to have the related object saved in the database first, inorder to define the relationship. Then, define the relationship using a.somefield.add(self). Then, save the a object. Otherwise, the relation won't be committed in the database.
I ended up utilizing post_save to get this to work.

How to pass instance ID as argument in property validator in Python?

I have an ndb.Model class and inside it there is a particular attribute that calls a certain function as validator:
class Article(ndb.Model):
itemList = ndb.StringProperty()
...
penInspc = ndb.IntegerProperty(default=0, indexed=True, validator=minPen)
I want the function minPen() to print the ID of the instance of class Article. How do I do that?
Just use a hook before put. This is as effective as a validator but also won’t mess up your queries in case you don’t have old data that do not respect the new validator rules.

How to initialize the datastore with a default entity in Google App Engine

Let say I have a particular model
class Page(db.Model):
""" Model for storing wiki pages """
page_name = db.StringProperty(required=True, default="/")
content = db.StringProperty(required=True, default="")
created = db.DateTimeProperty(auto_now = True)
What I want to do is query the data store. If there are no entities based on this model I want to create a default entity. Alternatively created the model with one default entity would be great.
I am aware of the init method in Python which is used to set initial values to attributes, but when I use this with the GAE & webapp2 within a Get method of a request handler I get an error.
The code that errors is:
class WikiPage(Handler):
def __init__(self):
pass
The error I see is:
handler = self.handler(request, response)
TypeError: __init__() takes exactly 1 argument (3 given)
Please advise
It's not clear what you are trying to do but if you simply want to rid of the error you need to define the __init__ method like this:
class WikiPage(Handler):
def __init__(self, *args, **kwargs):
pass
UPDATE to answer your question "why":
Because you are overriding the __init__ method of the Handler class which inherits from RequestHandler and if you take a look at its original definition here: https://code.google.com/p/webapp-improved/source/browse/webapp2.py#506 you'll see that that's how it is defined and that's how it is used throughout the framework which means if you for any reason decide to override it, you need to follow the same format.

Django using self on __init__ when not saved in database

Is it possible to use self as a reference in the __init__ method when the object is not instantiated yet?
What I'm trying to do is :
class MyClass(models.Model)
__init__(self):
some_attributes = AnotherClass.objects.filter(foreignkey=self)
The thing is that as the instance of MyClass is not registered in db yet, I have an exception like "MyClass has not attribute id"
I tried to add
if self.pk:
but it doesn't work. Is there a method like
if self.is_saved_in_db():
#some code
or do I have to created this one ?
EDIT
To be more specific, I'll give an example. I have a generic class which I try to hydrate with attributes from another Model.
class MyClass(models.Model)
_init__(self):
self.hydrate()
def hydrate(self):
# Retrieving the related objects
attributes = Information.objects.filter(...)
for attr in attributes:
attribute_id = attr.name.lower().replace(" ","_")
setattr(self,attribute_id,attr)
By doing so, I can access to attributes with MyClass.my_attribute.
For a small example, if we replace MyClass by Recipe and Information with Ingredients I can do :
pasta_recipe.pasta
pasta_recipie.tomato
pasta_recipie.onions
It's a simple parsing from a foreign_key to an attribute
By writing it, I realise that it's a bit useless because I can directly use ForeignKey relationships. I think I'll do that but for my own culture, is it possible do the filter with self as attribute before database saving ?
Thanks!
This is a very strange thing to do. I strongly recommend you do not try to do it.
(That said, the self.pk check is the correct one: you need to provide more details than "it doesn't work".)

Exposing a "dumbed-down", read-only instance of a Model in GAE

Does anyone know a clever way, in Google App Engine, to return a wrapped Model instance that only exposes a few of the original properties, and does not allow saving the instance back to the datastore?
I'm not looking for ways of actually enforcing these rules, obviously it'll still be possible to change the instance by digging through its __dict__ etc. I just want a way to avoid accidental exposure/changing of data.
My initial thought was to do this (I want to do this for a public version of a User model):
class PublicUser(db.Model):
display_name = db.StringProperty()
#classmethod
def kind(cls):
return 'User'
def put(self):
raise SomeError()
Unfortunately, GAE maps the kind to a class early on, so if I do PublicUser.get_by_id(1) I will actually get a User instance back, not a PublicUser instance.
Also, the idea is that it should at least appear to be a Model instance so that I can pass it around to code that does not know about the fact that it is a "dumbed-down" version. Ultimately I want to do this so that I can use my generic data exposure functions on the read-only version, so that they only expose public information about the user.
Update
I went with icio's solution. Here's the code I wrote for copying the properties from the User instance over to a PublicUser instance:
class User(db.Model):
# ...
# code
# ...
def as_public(self):
"""Returns a PublicUser version of this object.
"""
props = self.properties()
pu = PublicUser()
for prop in pu.properties().values():
# Only copy properties that exist for both the PublicUser model and
# the User model.
if prop.name in props:
# This line of code sets the property of the PublicUser
# instance to the value of the same property on the User
# instance.
prop.__set__(pu, props[prop.name].__get__(self, type(self)))
return pu
Please comment if this isn't a good way of doing it.
Could you not create a method within your User class which instantiates a ReadOnlyUser object and copies the values of member variables over as appropriate? Your call would be something like User.get_by_id(1).readonly() with the readonly method defined in the following form:
class User(db.Model):
def readonly(self):
return ReadOnlyUser(self.name, self.id);
Or you could perhaps have your User class extend another class with methods to do this automatically based on some static vars listing properties to copy over, or something.
P.S. I don't code in Python

Categories

Resources