So I'm trying to simulate a flags field in Django (4.0 and Python3) the same way I could do in C or C++. It would look like this:
typedef enum{
flagA = 0,
flagB,
flagC
} myFlags;
Having a uint8
that by default is 00000000
and then depending on if the flags are on or off I'd do some bitwise operations to turn the three least significant bits to 1 or 0.
Now, I could do that in my model by simply declaring a PositiveSmallIntegerField
or BinaryField
and just creating some helper functions to manage all this logic.
Note that I DO NOT NEED to be able to query by this field. I just want to be able to store it in the DB and very occasionally modify it.
Since it's possible to extend the Fields, I was wondering if it would be cleaner to encapsulate all this logic inside a custom Field inheriting from BinaryField. But I'm not really sure how can I manipulate the Field value from my custom class.
class CustomBinaryField(models.BinaryField):
description = "whatever"
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 1
super().__init__(*args, **kwargs)
For instance, if I wanted to create a method inside CustomBinaryField
, like the following, where the myFlagsStr
contains a str representation of the enum.
def getActiveFlags(self):
// For each bit which is set to 1 in the Binary value
// add it to an array with it's name such as: [flagA, flagC]
array = []
if self.value & (1 << myFlags.flagA):
array.append(myFlagsStr[flagA])
if self.value & (1 << myFlags.flagB):
array.append(myFlagsStr[flagB])
if self.value & (1 << myFlags.flagC):
array.append(myFlagsStr[flagC])
return array
Not sure how to get the actual value stored in the DB to make this if
comparisons.
Maybe mine is not the best approach to handle this, so I'm open to any suggestions you guys might have. But I think I could manage to do this the way I'm doing if I knew how to get the actual binary value from the DB from my functions.
I have seen there is a library https://github.com/disqus/django-bitfield that handles this but it limits to using only PostgreSQL and also, as mentioned before, I don't really need to filter by these flags, so something more simpler will do too.