Duelist
Duelist

Reputation: 11

Passing in a variable to a custom model field

Is it possible to pass in values to the init of a custom model field?

Example code:

class Example(models.Model):
    user = models.ForeignKey(User)
    text = EncryptedCharField('Text',max_length=255)

class BaseEncryptedField(models.Field):
    def __init__(self, *args, **kwargs):
        self.cipher = AES.new(key)
        models.Field.__init__(self, *args, **kwargs)            

    def to_python(self, value):
        if isinstance(value, EncryptedString):
            return self.cipher.decrypt(binascii.a2b_base64(str(value))).split(EOD)[0]
        return value

    def get_db_prep_value(self, value):
        if value is not None and not isinstance(value, EncryptedString):
            saltlength = self.cipher.block_size - (len(value) + len(EOD)) % self.cipher.block_size
            if saltlength:
               value = ''.join([value,EOD,generate_salt(saltlength)])
            value = EncryptedString(binascii.b2a_base64(self.cipher.encrypt(value)))
        return value    

In the init function, I'd like to pass a key (which is stored in the user profile and changes depending on the user) in to set up the AES cipher, but I can't seem to figure out how to get it in.

Upvotes: 1

Views: 405

Answers (2)

Francisco Passos
Francisco Passos

Reputation: 320

Try this. In class Example:

text = EncryptedCharField('Text', max_length=255, key=pass_the_user's_key_here)

Then in BaseEncryptedField.init:

self.cipher = AES.new(kwargs['key'])

Upvotes: 0

pcalcao
pcalcao

Reputation: 15965

Not sure I understand your problem... but here goes.

If you pass the argument to the constructor of your model (init), it'll be available in the "args" collection. You can also pass arguments as a map (so you can access them by name through kwargs).

So you should do something like args[0], to get your key. (Can't remember exactly if the first passed parameter is at index 0 or 1, you can always try it out/debug =))

Upvotes: 1

Related Questions