Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#14 #15 Serialize EDTFField values into DB #16

Merged
merged 2 commits into from
Jun 5, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions edtf/fields.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
try:
import cPickle as pickle
except:
import pickle

from django.db import models

from edtf import parse_edtf, EDTFObject
Expand All @@ -22,7 +27,7 @@ def __init__(
upper_fuzzy_field=None,
**kwargs
):
kwargs['max_length'] = 255
kwargs['max_length'] = 2000
self.natural_text_field, self.lower_strict_field, \
self.upper_strict_field, self.lower_fuzzy_field, \
self.upper_fuzzy_field = natural_text_field, lower_strict_field, \
Expand All @@ -48,6 +53,12 @@ def deconstruct(self):

def from_db_value(self, value, expression, connection, context):
# Converting values to Python objects
if not value:
return None
try:
return pickle.loads(str(value))
except:
pass
return parse_edtf(value, fail_silently=True)

def to_python(self, value):
Expand All @@ -59,11 +70,16 @@ def to_python(self, value):

return parse_edtf(value, fail_silently=True)

def get_db_prep_save(self, value, connection):
if value:
return pickle.dumps(value)
return super(EDTFField, self).get_db_prep_save(value, connection)

def get_prep_value(self, value):
# convert python objects to query values
value = super(EDTFField, self).get_prep_value(value)
if isinstance(value, EDTFObject):
return unicode(value)
return pickle.dumps(value)
return value

def pre_save(self, instance, add):
Expand All @@ -74,19 +90,29 @@ def pre_save(self, instance, add):
if not self.natural_text_field or self.attname not in instance.__dict__:
return

edtf = getattr(instance, self.attname)

# Update EDTF field based on latest natural text value, if any
natural_text = getattr(instance, self.natural_text_field)
if natural_text:
n = text_to_edtf(natural_text)
setattr(instance, self.attname, n)
edtf = text_to_edtf(natural_text)

e = parse_edtf(getattr(instance, self.attname), fail_silently=True)
if e:
# TODO If `natural_text_field` becomes cleared the derived EDTF field
# value should also be cleared, rather than left at original value?

# TODO Handle case where EDTF field is set to a string directly, not
# via `natural_text_field` (this is a slightly unexpected use-case, but
# is a very efficient way to set EDTF values in situations like for API
# imports so we probably want to continue to support it?)
if edtf and not isinstance(edtf, EDTFObject):
edtf = parse_edtf(edtf, fail_silently=True)

setattr(instance, self.attname, edtf)
if edtf:
# set related date fields on the instance
for attr in DATE_ATTRS:
field_attr = "%s_field" % attr
g = getattr(self, field_attr, None)
if g:
setattr(instance, g, getattr(e, attr)())

return unicode(e)
setattr(instance, g, getattr(edtf, attr)())
return edtf