10

I am trying to build a document object using from_json method. object.save() throws no error, but the document is not inserted in mongo.

On the other hand if I make the object by assigning values to each of the fields, it works fine.

I am unable to find the reason for this. Below is the code for both the cases.

from flask import Flask
from flask.ext.mongoengine import MongoEngine
import json, datetime

app = Flask(__name__)
app.config["MONGODB_SETTINGS"] = {'DB': 'test','host': 'localhost'}
app.config["SECRET_KEY"] = "mySecretKey"

db = MongoEngine(app)
class User(db.Document):
    user_id = db.StringField(max_length=16, primary_key = True)
    username = db.StringField(min_length=8)
    email = db.EmailField(required = True, unique = True)
    password = db.StringField(required = True)
    date_of_birth = db.DateTimeField()
    gender = db.StringField(choices = ('M', 'F'))

'''
    This one works. This will add a user in local mongodb(test)
'''
u1 = User()
u1.username = 'test12345'
u1.user_id = 'testid12345'
u1.email = 'test@test.com'
u1.password = 'testerpass'
u1.save()

'''
    This one doesn't works.
'''
u2 = User()
temp_json = {'username':'test2_12345','user_id':'testid2@12345','password':'testerpass2','email':'test2@test.com'}
u2 = u2.from_json(json.dumps(temp_json))
u2.save()
BabbarTushar
  • 1,285
  • 2
  • 11
  • 20

3 Answers3

15

A mongoengine document object can be initialised with **kwargs. Thus using this we can implement the from_json functionality in the following way :-

obj_dict = {
    'key1' : 'value1',
    'key2' : 'value2'
}
user = User(**obj_dict) # User is a mongoengine document object

This worked for me.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
BabbarTushar
  • 1,285
  • 2
  • 11
  • 20
  • and one of your Mongo-style JSON fields was a date in the format `timestamp: { $date: 1440027939372 }`, right? – Phlip Aug 30 '15 at 23:12
6

from_json() is convert to JSON data an unsaved document instance. Do save of unsaved document is use parameter force_insert=True.

...
>>> User.objects
[<User: test1-12345>]
>>> u2.save()
>>> User.objects
[<User: test1-12345>]
>>> u2.save(force_insert=True)
>>> User.objects
[<User: test1-12345>, <User: test2-12345>]

But, your code I can.

I can not code here. (I need fixture data of unit test.)

I environment Django 1.6.5 and mongoengine 0.8.7

>>> json_data1 = u1.to_json()
>>> User.objects.delete() # or User.drop_collection()
>>> User.objects
[]
>>>
...
# json_data1 to dump for pickle. Next load for pickle.
...
>>> u1 = User.from_json(json_data1)
>>> u1.save()
>>> User.objects
[]
>>> u1.save(force_insert=True)
>>> User.objects
[<User: test1-12345>]
>>>

force_insert=True is only try to create a new document.

Every time use force_insert=True is create a new document.

Use force_insert=False is get document in database.

Zulu
  • 8,765
  • 9
  • 49
  • 56
bindi
  • 121
  • 2
  • 5
-2

You are assigning u2 to the result of from_json(), and losing reference to the original User object.

Change u2 = u2.from_json(... to u2.from_json(...

Rishi
  • 268
  • 1
  • 6
  • The from_json method returns a **document object** with the fields provided in the json assigned to the object. Thus this returned object must be done object.save(). If u2 is not assigned the value returned from the from_json() method it remains to be an empty user document object. – BabbarTushar Feb 13 '14 at 06:08
  • u2.from_json(... does not assign values to the original u2. – shshank Feb 13 '14 at 06:39