Django - Custom virtual model field with companion

2019-06-09 14:45发布

I would like to have a ConfirmationField field type. I want this field to work like a boolean field. I don't need to store this information on database instead I would like to store the date of confirmation on a seperate field.

class MyModel(models.Model):
    confirmation = ConfirmationField()


m = MyModel()
m.confirmation # False
m.confirmation_timestamp # None

m.confirmation = True
m.save()

m.confirmation_timestamp # datetime object


m.confirmation = False
m.save()

m.confirmation_timestamp # None again

I need to have both fields as Field instances, I need to be able to use them in Admin for example.

I have read the docs and checked the code, ForeignKey changes its database column name with the following code:

def get_attname(self):
    return '%s_id' % self.name

But I couldn't figure out exacly how I can use the rest of the code as an example. It seems my goal doesn't require tto much complexity.

I have also found ImageField saved extra information when the model is saved:

    if self.field.width_field:
        setattr(self.instance, self.field.width_field, self.width)
    if self.field.height_field:
        setattr(self.instance, self.field.height_field, self.height)

But of course I don't want confirmation itself to be stored in the database. I would cause redundancy since (confirmation_timestamp -> confirmation) None==False and <datetime instance>==True.

Any pointers/ideas are appreciated.

Thanks.

edit: It appears this is not currently possible. I have ended up changing my API. Here is a snipplet to give an idea how I did it:

    value = {'BooleanField': True,
             'DateTimeField': datetime.datetime.now(),
             'DateField': datetime.date.today(),
             'IntegerField': 1,
            }[instance._meta.get_field(field_name).get_internal_type()]
    setattr(instance, field_name, value)

You can have a confirmation field any type mentioned above and it sets the correct value. And confirmation checking can be done with bool(getattr(instance, field_name).

1条回答
一纸荒年 Trace。
2楼-- · 2019-06-09 15:01

if I got this right, consider:

class Modelname(models.Model):
    """(Modelname description)"""

    confirmation_timestamp = models.DateTimeField(blank=True)

    def _set_confirmation(self, value):
        if not value:
            self.confirmation_timestamp = None
        else:
            self.confirmation_timestamp = datetime.datetime.now()

    def _get_confirmation(self):
        return bool(self.confirmation_timestamp)

    confirmation = property(_get_confirmation, _set_confirmation)
    confirmation.short_description = "Confirmation"
    confirmation.boolean = True # have it nicely displayed in admin
查看更多
登录 后发表回答