Embedded Documents issue with MongoEngine - python

I am using MongoDB with Flask-MongoEngine as my ORM component to my web app.
I have structured the User document schema like so:
from ..core import db
class UserComics(db.EmbeddedDocument):
favorites = db.SortedListField(db.StringField(), default=None)
class UserSettings(db.EmbeddedDocument):
display_favs = db.BooleanField(default=False)
default_cal = db.StringField(default=None)
show_publishers = db.ListField(db.StringField(), default=None)
class UserTokens(db.EmbeddedDocument):
refresh_token = db.StringField(default=None)
access_token = db.StringField(default=None)
expire_time = db.StringField(default=None)
class User(db.Document, UserMixin):
# Save User document to this collection
meta = {'collection': 'users_test'}
userid = db.StringField()
full_name = db.StringField()
first_name = db.StringField()
last_name = db.StringField()
gender = db.StringField()
birthday = db.StringField()
email = db.EmailField()
friends = db.ListField(db.StringField())
date_creation = db.DateTimeField()
last_login = db.DateTimeField()
favorites = db.EmbeddedDocumentField(UserComics)
settings = db.EmbeddedDocumentField(UserSettings)
tokens = db.EmbeddedDocumentField(UserTokens)
However, When creating a new user like this (I have left out lines...):
def create_new_user(resp):
newUser = User()
....
newUser.settings.default_cal = resp['calendar']
....
newUser.save()
return
I run into this error:
AttributeError: 'NoneType' object has no attribute 'default_cal'
It seems to me that I am not using MongoEngines Embedded documents correctly but I do not know where I am going wrong.
Any help would be greatly appreciated!

Well you just have to create an embedded document object of the particular class, and then use it with the main document class, like so:
new_user = User()
user_settings = UserSettings()
user_settings.default_cal = resp['calendar']
new_user.settings = user_settings
# more stuff
new_user.save()
Note: Creating a new object only for the main document, does not automatically create the corresponding embedded document object(s), but while reading data ofcourse the case is different.
Edit:
As tbicr mentions below, we can also do this:
settings = db.EmbeddedDocumentField(UserSettings, default=UserSettings)
while declaring the field, that way we won't need to create the object as given in the first example.

Related

Mongoengine: A ReferenceField only accepts DBRef, LazyReference, ObjectId or documents

I am new to python flask. I am creating an API for user registration where a user may have multiple languages. so I am referencing list of languages in my user object.
please get my code here..
class User(Document):
name = StringField(required=True)
email = EmailField(required=True, primary_key=True)
languages = ListField(ReferenceField(Language), required=True)
class Language(Document):
name = StringField(required=True, unique=True)
active = BooleanField(default=True)
#app.route("/register", methods=["POST"])
def register_user():
request_payload = request.json
user = User(
name = request_payload["name"],
email = request_payload["email"]
)
for lang in request_payload["languages"]:
user.languages.append(Language.objects(name=lang))
user.save()
**Post request Payload
======================**
{
"name":"xxxx",
"email":"xxx#gmail.com",
"languages":["English","Marathi"]
}
**Error:
========**
ValidationError (User:xxx#gmail.com) (A ReferenceField only accepts DBRef, LazyReference, ObjectId or documents: ['languages'])
Document object returns QuerySet ..it was causing that error. ..for loop changed and it worked
for lang in request_payload["languages"]:
obj = Languages.objects(name=lang)
# print("******" + str(obj.count()), file=sys.stdout)
if obj.count() == 0:
return error_return("Incorrect Language: "+lang+ " is not present in Languages collection", 400)
for l1 in obj:
user.languages.append(l1)

django - prepending a field in the query set that doesn't exist in the model

I have a model that reads from a pre-existing university database. The username is stored as the students id. I'm not able to add a new column to the database in a save or I could use a save function in my model.
class Student(models.Model):
student_id = models.IntegerField(db_column = 'Student_ID', primary_key = True)
statusid = models.IntegerField(db_column = 'StatusID')
fname = models.CharField(db_column = 'Student_First_Name', max_length = 35)
lname = models.CharField(db_column = 'Student_Last_Name_Formatted' , max_length = 40)
class Meta:
managed = False
db_table = '[Student]'
What i'm trying to do is take the username in a query and match it up with another field that is umich.edu/student_id as a primary key.
I'm defining the request in one function as:
def user_list(request):
student = Student.objects.all()
passing in the argument for students to my template with a POST to the form.
In my next view that gets posted
def criteria(request):
user = request.POST.get('student_id')
print(user)
student = CourseCriteria.objects.get(universitystudentid = request.POST.get('student_id'))
My print/post of user is coming through correctly as the student id, but I need to prepend umich.edu/ to the student_id in the queryset. How can I accomplish this without being able to add that field to my model?
I am not sure to understand your problem, I suppose that it is not as simple as:
def criteria(request):
user = request.POST.get('student_id')
student = CourseCriteria.objects.get(universitystudentid='umich.edu/%s'%user)

Python Mongoalchemy Ref field at same class

Im stuck trying to solve this:
class User(db.Document):
date_add = db.CreatedField()
date_update = db.ModifiedField()
username = db.StringField()
password = db.StringField()
active = db.BoolField()
admin = db.BoolField()
user_add = db.IntField()
user_update = db.IntField()
user_add = db.SRefField(type = User, default = None)
ser_update = db.SRefField(type = User, default = None)
console says: NameError: name 'User' is not defined, there is some way to handle this?
UPDATE
i ve found the same problem while using the DocumentField class, defining a field like myfield= db.DocumentField(Myclass)inside Myclass create the same error above and cant still figure it out

When creating a model instance how to fill ManyToMany field?

I want to create model instance like this:
new_tweet = Tweet.objects.create(text = tweet_object.text, date = tweet_object.date, username = tweet_object.username, retweet = tweet_object.retweet.all(), is_ret = True)
It's all going well until this: retweet = tweet_object.retweet.all(). It returns this error: 'retweet' is an invalid keyword argument for this function
This is a ManyToMany field. So how to fill this field when creating new model instance?
By the way tweet_object.retweet.all() is consisted of many retweetobjects.
EDIT:
Model:
class Tweet(models.Model):
text = models.CharField(max_length=140)
date = models.DateTimeField(auto_now_add=True)
username = models.CharField(max_length=140)
favourite = models.ManyToManyField(Favourite)
retweet = models.ManyToManyField(Retweet)
replies = models.ManyToManyField('Tweet')
is_ret = models.BooleanField(default=False)
def __unicode__(self):
return self.username
And tweet_object, which is just another tweet:
tweet_object = Tweet.objects.get(id=tweet_id)
I think you should create Tweet object first and next you can create relations with retweets.
More about information you can find here: https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
It's very simply:
tweet_object = Tweet.objects.get(id=tweet_id)
new_tweet = Tweet.objects.create(text = tweet_object.text, date = tweet_object.date, username = tweet_object.username, is_ret = True)
for retweet in tweet_object.retweet.all():
new_tweet.retweet.add(retweet)
new_tweet.save()

Google App Engine Django BooleanProperty not binding to table

I have the following,
class Company(db.Model):
companyvalid = db.BooleanProperty(required=True)
class AddCompanyForm(djangoforms.ModelForm):
class Meta:
model = Company
exclude = ['companyentrytime']
exclude = ['companylatlong']
however I cannot get the o/p from the Django stored in the database. I can also only add a record when the checkbox is checked, but this is not reflected in the underlying table when saving the record. What is the smartest way to do this? Thanks
class AddCompanyCategoriesHandler(webapp.RequestHandler):
def get(self):
memcache.flush_all()
form_requirements = AddCompanyCategoriesForm()
path = os.path.join(os.path.dirname(__file__), 'addcompanycat.html')
self.response.out.write(template.render(path, {'form': form_requirements}))
def post(self):
form_requirements = AddCompanyCategoriesForm(data=self.request.POST)
if form_requirements.is_valid():
myname = form_requirements.clean_data['categoryname']
entity = form_requirements.save(commit=False)
entity.put()
=========================================================================================
I'm trying to use the BooleanField, but this fails to work, with the server giving out a 504 error. Here is my model. I've been experimenting with this BooleanFields format, but I'm not sure how this relates to my model. My model is
class Company(db.Model):
companyurl = db.StringProperty(required=True)
companyname = db.StringProperty(required=True)
companydesc = db.TextProperty(required=True)
companyaddress = db.PostalAddressProperty(required=True)
companypostcode = db.StringProperty(required=True)
companyemail = db.EmailProperty(required=True)
companycountry = db.StringProperty(required=True)
companyvalid = db.BooleanProperty()
#companyvalid = db.BooleanField(required=True, label="Check this")
companyentrytime = db.DateTimeProperty(auto_now_add=True)
companylatlong = db.GeoPtProperty()
#property
def catname(self):
return self.companycategory.name
companycategory = db.ReferenceProperty(CompanyCategory, collection_name='compcategory')
and the following
class AddCompanyForm(djangoforms.ModelForm):
class Meta:
model = Company
#companyvalid = model.BooleanField(default=False)
exclude = ['companyentrytime']
exclude = ['companylatlong']
So my question is that if I have to use this BooleanField, how should I put it in the AddCompanyForm and should there be an entry in the model?
Try using BooleanField (https://docs.djangoproject.com/en/dev/ref/models/fields/#booleanfield) rather than Boolean Property in your model?

Categories

Resources