I have the following code:
session = scoped_session(sessionmaker(autocommit=False, autoflush=True, bind=engine))
Base = declarative_base()
Base.query = session.query_property()
class CommonBase(object):
created_at = Column(DateTime, default=datetime.datetime.now)
updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)
class Look(Base, CommonBase):
__tablename__ = "looks"
id = Column(Integer, primary_key=True)
def __init__(self):
print "__init__ is run"
Base.__init__(self)
self.feedback = None
def set_feedback(self, feedback):
"""Status can either be 1 for liked, 0 no response, or -1 disliked.
"""
assert feedback in [1, 0, -1]
self.feedback = feedback
def get_feedback(self):
return self.feedback
And I am getting the following error:
Traceback (most recent call last):
File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/Volumes/Data2/Dropbox/projects/Giordano/venv/lib/python2.7/site-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/backend.py", line 94, in wrapped
ret = f(*args, **kwargs)
File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/backend.py", line 81, in decorated
return f(*args, **kwargs)
File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/web/backend.py", line 187, in next
json_ret = ge.encode(results) # automatically pulls the tags
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/__init__.py", line 54, in default
jsonable = self.convert_to_jsonable(obj)
File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/__init__.py", line 40, in convert_to_jsonable
image_url=obj.image_url, feedback=obj.get_feedback())
File "/Volumes/Data2/Dropbox/projects/Giordano/src/giordano/models.py", line 100, in get_feedback
return self.feedback
AttributeError: 'Look' object has no attribute 'feedback'
It seems to me that my __init__ method is not run as I can't see any print statements in my log.
Can someone explain why my __init__ is not run and what can I do for this?
Check out the SQLAlchemy documentation on reconstruction:
The SQLAlchemy ORM does not call __init__ when recreating objects from
database rows. The ORM’s process is somewhat akin to the Python
standard library’s pickle module, invoking the low level __new__
method and then quietly restoring attributes directly on the instance
rather than calling __init__.
If you need to do some setup on database-loaded instances before
they’re ready to use, you can use the #reconstructor decorator to tag
a method as the ORM counterpart to __init__. SQLAlchemy will call this
method with no arguments every time it loads or reconstructs one of
your instances. This is useful for recreating transient properties
that are normally assigned in your __init__:
from sqlalchemy import orm
class MyMappedClass(object):
def __init__(self, data):
self.data = data
# we need stuff on all instances, but not in the database.
self.stuff = []
#orm.reconstructor
def init_on_load(self):
self.stuff = []
When obj = MyMappedClass() is executed, Python calls the __init__
method as normal and the data argument is required. When instances are
loaded during a Query operation as in query(MyMappedClass).one(),
init_on_load is called.
Related
I tried to add a list to an attribute but when I tried to save the db it raises the exception below. Is there something wrong with my code? I previously modified the models to add new attribute saved_jadwal_ids. I thought it caused no problem as I've tried to set value to it before doing jadwal.save() and I could print the value. Do I actually need to make migrations or something? Thank you.
jadwal = Jadwal.objects(id=jadwal_id).first()
eventIds = []
# courses = data['jadwals']
courses = getCourses()
for course in courses:
id = insert_event(calendar, course)
eventIds.append(id)
jadwal.saved_jadwal_ids = eventIds
jadwal.save()
Jadwal.py:
class Jadwal(Document):
user_id = ReferenceField('User')
jadwals = ListField(EmbeddedDocumentField(JadwalData))
created_at = DateTimeField(default=datetime.now)
saved_jadwal_ids = ListField(StringField)
Error:
Traceback (most recent call last):
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask\app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask_cors\extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\Anisha\RISTEK BISMILLAH\sunjadv2-server\app.py", line 631, in add_jadwal_to_calendar
jadwal.save()
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\mongoengine\document.py", line 362, in save
self.validate(clean=clean)
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\mongoengine\base\document.py", line 377, in validate
field._validate(value)
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\mongoengine\base\fields.py", line 234, in _validate
self.validate(value, **kwargs)
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\mongoengine\fields.py", line 857, in validate
super(ListField, self).validate(value)
File "c:\users\anisha\appdata\local\programs\python\python37\lib\site-packages\mongoengine\base\fields.py", line 431, in validate
self.field._validate(v)
TypeError: _validate() missing 1 required positional argument: 'value'
Try replacing:
saved_jadwal_ids = ListField(StringField)
with:
saved_jadwal_ids = ListField(StringField())
I could reproduce and fix the error with this snippet:
from mongoengine import Document, StringField, ListField
class Example(Document):
meta = {'collection': 'examples'}
saved_jadwal_ids = ListField(StringField) # should be StringField()
e = Example()
e.saved_jadwal_ids = ['not','ok']
e.save()
TypeError: _validate() missing 1 required positional argument: 'value'
I'm trying to create a custom validator for one field in the AddSongForm. I used the inline validator and it uses two methods from my Songs class. When I try running the code, I get the following trace back:
form = AddSongForm()
[2017-05-16 13:44:11,547] ERROR in app: Exception on /addsong [POST]
Traceback (most recent call last):
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Python36-32\lib\site-packages\flask\_compat.py", line 33, in reraise
raise value
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Python36-32\lib\site-packages\flask\app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python36-32\lib\site-packages\flask_login\utils.py", line 228, in decorated_view
return func(*args, **kwargs)
File "C:/Users/Pellissari/Desktop/files/projects/Musical 9gag/view.py", line 40, in addsong
if form.validate_on_submit():
File "C:\Python36-32\lib\site-packages\flask_wtf\form.py", line 101, in validate_on_submit
return self.is_submitted() and self.validate()
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 310, in validate
return super(Form, self).validate(extra)
File "C:\Python36-32\lib\site-packages\wtforms\form.py", line 152, in validate
if not field.validate(self, extra):
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 204, in validate
stop_validation = self._run_validation_chain(form, chain)
File "C:\Python36-32\lib\site-packages\wtforms\fields\core.py", line 224, in _run_validation_chain
validator(form, self)
File "C:\Users\Pellissari\Desktop\files\projects\app\forms.py", line 20, in validate_song_link
if Songs.get_provider(url) in valid_providers:
TypeError: get_provider() missing 1 required positional argument: 'url'
127.0.0.1 - - [16/May/2017 13:44:11] "POST /addsong HTTP/1.1" 500 -
This is my form class
class AddSongForm(Form):
song_title = StringField('song_title', validators=[DataRequired()])
song_artist = StringField('song_artist', validators=[DataRequired()])
song_genre = StringField('song_genre')
song_link = StringField('song_link', validators=[DataRequired()])
def validate_song_link(form, song_link):
valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
url = song_link.data
if Songs.get_provider(url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
else:
print("couldn't get your content")
return False
else:
print("unsupported provider")
return False
And here is the class I used the methods
class Songs(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
title = db.Column(db.String(50))
artist = db.Column(db.String(30))
genre = db.Column(db.String(40))
author = db.Column(db.String(40))
timestamp = db.Column(db.DateTime)
likes_num = db.Column(db.Integer)
song_link = db.Column(db.String(120))
def get_provider(self, url):
return urllib.parse.urlsplit(url)[1]
def get_embed_code(self, url):
code = None
vars = {'url': url, 'format': 'json', 'iframe': 'true', 'maxwidth': '450', 'show_comments': 'false'}
provider = self.get_provider(url)
endpoint = "http://"+provider+"/oembed?"
source = endpoint+urllib.parse.urlencode(vars)
try:
request = urlopen(source)
code = json.load(request)['html']
return code
except:
print("impossible to get your content. Check the link")
return False
I'm quite new with Python and this is my first time writing OO code, so I have no idea what could be happening here. Besides the problem, I would be happy if you also could give me some feedback on the code and if there are room to improve in some sense.
I'm not convinced these should be methods on Songs. They don't refer to anything to do with the Song class.
However if you want to keep them as methods, but still want to call them from the class, they need to be classmethods, not instance methods.
#classmethod
def get_provider(cls, url):
return urllib.parse.urlsplit(url)[1]
#classmethod
def get_embed_code(cls, url):
...
provider = cls.get_provider(url)
First of all correct the indentation for the method validate_song_link. It should be like this:
def validate_song_link(form, song_link):
valid_providers = ['youtube.com', 'www.youtube.com', 'soundcloud.com', 'www.soundcloud.com']
url = song_link.data
if Songs.get_provider(url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
else:
print("couldn't get your content")
return False
else:
print("unsupported provider")
return False
To solve your problem you can try to change the get_provider method to a class method like this:
#classmethod
def get_provider(cls, url):
return urllib.parse.urlsplit(url)[1]
And then you can call this way:
songs = Songs()
if Songs.get_provider(songs, url) in valid_providers:
if Songs.get_embed_code(url) is not False:
return True
I have been stumped and can't seem to figure out why I am receiving an AssertionError. I am currently working on a rest api using the flask_restful lib. I am querying by:
#staticmethod
def find_by_id(id, user_id):
f = File.query.filter_by(id=id).first() #Error is happening here
if f is not None:
if f.check_permission(user_id)>=4:
return f
print f.check_permission(user_id)
FileErrors.InsufficientFilePermission()
FileErrors.FileDoesNotExist()
The error message looks like this:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 2000, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1991, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1567, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 268, in error_router
return self.handle_error(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1988, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1641, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1531, in handle_user_exception
assert exc_value is e
AssertionError
This is how my File model looks like:
class File(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer)
parts = db.Column(db.Integer)
size = db.Column(db.Integer)
name = db.Column(db.String(100))
def __init__ (self, file_info):
self.user_id = file_info['user_id']
self.parts = file_info['parts']
self.size = file_info['size']
self.name = file_info['name']
#staticmethod
def create(file_info):
return add_to_db(File(file_info))
#staticmethod
def delete(file_id, user_id):
pass
def check_permission(self,user_id):
permission = 0
print 'self.user_id {}'.format(self.user_id)
print 'user_id {}'.format(user_id)
if self.user_id == user_id:
return 7
fs = FileShare.find_by_file_and_user_id(self.id, user_id)
if fs is not None:
permission = fs.permission
return permission
#staticmethod
def find_by_id(id, user_id):
f = File.query.filter_by(id=id).first() #Error is happening here
if f is not None:
if f.check_permission(user_id)>=4:
return f
print f.check_permission(user_id)
FileErrors.InsufficientFilePermission()
FileErrors.FileDoesNotExist()
Any help would be appreciated. Thanks in advance.
Are you sure you want to have an assignment operator instead of comparison in your filter. Try replacing = with == and see if it solves your problem.
f = File.query.filter_by(id == id).first()
Hannu
Although I couldn't figure out why the error occurs, I know how as well as how to prevent it. It is created because the query doesn't pull the live data right after the commit. The way to prevent it is by using db.session.query(). So in my example I would change:
f = File.query.filter_by(id=id).first()
to
f = db.session.query(File).filter_by(id=id).first()
For some reason that works. Although I don't know why.
EDIT: It seems to have to do with the class not receiving updated session. For the time being I recommending using queries within session.
I'm getting the following error on Google App Engine when I attempt to post a image (blob) and some other data to the datastore through a Web form. The code works on my local machine, but not when I upload to the GAE environment. :
<type 'str'> has type <type 'str'>, but expected one of: int, long, bool
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~mygrajj/1.371507856337629790/main.py", line 123, in post
car.put()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 3232, in _put
return self._put_async(**ctx_options).get_result()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 325, in get_result
self.check_success()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 368, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 748, in put
key = yield self._put_batcher.add(entity, options)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py", line 371, in _help_tasklet_along
value = gen.send(val)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/context.py", line 280, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py", line 1574, in async_put
pbs = [self.__adapter.entity_to_pb(entity) for entity in entities]
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 570, in entity_to_pb
pb = ent._to_pb()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 2945, in _to_pb
prop._serialize(self, pb, projection=self._projection)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py", line 1297, in _serialize
p.set_multiple(self._repeated or parent_repeated)
File "cpp_message.pyx", line 124, in cpp_message.SetScalarAccessors.Setter (third_party/apphosting/python/protobuf/proto1/cpp_message.cc:2229)
TypeError: <type 'str'> has type <type 'str'>, but expected one of: int, long, bool
When trying to execute the following code:
class AddCar(blobstore_handlers.BlobstoreUploadHandler, webapp2.RequestHandler):
def post(self):
car = Car()
if self.get_uploads('file'):
upload_files = self.get_uploads('file') # 'file' is file upload field in the form
blob_info = upload_files[0]
car.CarBlobKey = blob_info.key()
car.CarImageServingURL.append(images.get_serving_url(blob_info.key()))
car.CarYear = self.request.get('modelyear0')+self.request.get('modelyear1')+self.request.get('modelyear2')
car.CarMake = self.request.get('makeField')
car.CarModel = self.request.get('modelField')
car.CarPosterGrajjStatus = self.request.get('which_grajj')
if users.get_current_user():
car.CarPoster = users.get_current_user()
car.put()
#grajj_query = Car.query()
#cars = grajj_query.fetch(100)
self.redirect('/mygrajj.html')
Here's my model:
class Car(ndb.Model):
# Car class contains data on a prototype car
CarYear = ndb.StringProperty()
CarMake = ndb.StringProperty()
CarModel = ndb.StringProperty()
CarPoster = ndb.UserProperty()
CarPosted = ndb.DateTimeProperty(auto_now_add="true")
CarPosterGrajjStatus = ndb.StringProperty()
CarBlobKey = ndb.BlobKeyProperty(indexed="false")
CarImageServingURL = ndb.StringProperty(indexed="false", repeated="true")
The code works on my local machine, but not when it's deployed
How about drop the blob and isolate where the problem is.
I think this line will reference a NoneType since CarImageServingURL does not have a default value.
car.CarImageServingURL.append(images.get_serving_url(blob_info.key()))
You could rewrite it as
car.CarImageServingURL = images.get_serving_url(blob_info.key())
Or try changing the definition to have a default:
CarImageServingURL = ndb.StringProperty(indexed="false", repeated="true", default="")
you need to change all the parameter to Boolean
class Car(ndb.Model):
# Car class contains data on a prototype car
CarYear = ndb.StringProperty()
CarMake = ndb.StringProperty()
CarModel = ndb.StringProperty()
CarPoster = ndb.UserProperty()
CarPosted = ndb.DateTimeProperty(auto_now_add="true")
CarPosterGrajjStatus = ndb.StringProperty()
CarBlobKey = ndb.BlobKeyProperty(indexed="false")
CarImageServingURL = ndb.StringProperty(indexed="false", repeated="true")
auto_now_add=True
indexed=False
repeated=True
ommit the ""
I'm trying to output results of my mysql query to JSON.
I have problem with serializing datetime.datetime field, so I wrote small function to do that:
def date_handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
return obj
and then in main code I'm just running:
products_json = []
for code in best_matching_codes:
cur = db.cursor()
query = "SELECT * FROM %s WHERE code LIKE '%s'" % (PRODUCTS_TABLE_NAME, product_code)
cur.execute(query)
columns = [desc[0] for desc in cur.description]
rows = cur.fetchall()
for row in rows:
products_json.append(dict((k,v) for k,v in zip(columns,row)))
return json.dumps(products_json, default = date_handler)
However, since I wrote date_handler function, I'm getting "ValueError: Circular reference detected"
127.0.0.1 - - [10/Jan/2013 00:42:18] "GET /1/product?code=9571%2F702 HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/flask/app.py", line 1701, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1689, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/pisarzp/Desktop/SusyChoosy/susyAPI/test1.py", line 69, in product_search
return json.dumps(products_json, default = date_handler)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 201, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 264, in iterencode
return _iterencode(o, 0)
ValueError: Circular reference detected
What did I break? Is there a better way to serialize output to JSON?
The function you pass as the default argument will only be called for objects that are not natively serializable by the json module. It must return a serializable object, or raise a TypeError.
Your version returns the same object you were passed if it's not of the one type you're fixing (dates). That is causing the circular reference error (which is misleading, since the circle is between one object and itself after being processed by date_handler).
You can start to fix this by changing date_handler to raise an exception in its else block. That will still probably fail, but you can probably then find out what object it is that is in your data structure causing the problem using code like this:
def date_handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
raise TypeError(
"Unserializable object {} of type {}".format(obj, type(obj))
)
Instead of raising the TypeError yourself, you should relay the call to JSONEncoder's default-method:
def date_handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
else:
json.JSONEncoder.default(self,obj)
This will also raise TypeError and is a better practice, it allows for JSONEncoder to try and encode the type your method can't.
json.dumps(obj, default=method_name)
"method_name" function must be return a serialize object.
def method_name(obj):
data = {
'__class__': obj.__class__.__name__,
'__module__': obj.__module__
}
data.update(obj.__dict__)
return data