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

Migrations with Fingerprint Fields #2

Open
jan-grimo opened this issue Apr 7, 2016 · 0 comments
Open

Migrations with Fingerprint Fields #2

jan-grimo opened this issue Apr 7, 2016 · 0 comments

Comments

@jan-grimo
Copy link

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!

rvianello pushed a commit that referenced this issue Oct 31, 2018
…-value

add a few tests using sql expressions to operate on a MolField column
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant