-
Notifications
You must be signed in to change notification settings - Fork 29
Description
I recently tried to add a fingerprint field to a model and then perform a migration. Following the documentation, which suggests
class django_rdkit.models.BfpField(**options)
A bit vector fingerprint. It may be assigned using an ExplicitBitVect instance or with an update query using one of the implemented fingerprint functions.
I attempted to set a default using an instance of ExplicitBitVect like so:
class Compound(models.Model):
[...]
morganbv_fp = models.BfpField(default=ExplicitBitVect(1))to which Django's makemigrations complains that ExplicitBitVect is unserializable. Since it is initializable with an unsigned integer which Django can serialize just fine, I derived the class and decorated it (see Django Docs Migration Serializing):
from django.utils.deconstruct import deconstructible
[...]
@deconstructible
class DeconExplicitBitVect(ExplicitBitVect):
pass
[...]
class Compound(models.Model):
[...]
morganbv_fp = models.BfpField(default=DeconExplicitBitVect(1))This allows the class to be serialized and makemigrations passes, but migrate fails due to:
django.db.utils.ProgrammingError: column "morganbv_fp" is of type bfp but default expression is of type bytea
The SQL expression generated by makemigrations is:
BEGIN;
--
-- Add field morganbv_fp to compound
--
ALTER TABLE "rest_compound" ADD COLUMN "morganbv_fp" bfp DEFAULT '\000'::bytea NOT NULL;
ALTER TABLE "rest_compound" ALTER COLUMN "morganbv_fp" DROP DEFAULT;
COMMIT;Which is of course nonsense. Now I don't know where exactly this would be corrected, but I suspect it's due to models/fields.py:
[...]
class BfpField(Field):
[...]
def get_prep_value(self, value):
# convert the ExplicitBitVect instance to the value used by the
# db driver
if isinstance(value, ExplicitBitVect):
value = six.memoryview(DataStructs.BitVectToBinaryText(value))
return value
[...]I fixed it by just setting the field to be nullable and the default null. It doesn't really matter whether I fill it with a nonsensical sfp instance or just allow it to be null in practice to me.
Is there a better way I completely missed? Otherwise I would recommend adapting the documentation to suggest allowing the fingerprint fields to be null in order for migrations to work.
Cheers and thanks for your time!