4

I want to define a setter function for a Django model field in order to validate the input and immediately raise a error if value is not valid.

I don't think that doing the validation in save() or pre_save() is a feasible solution for my problem because of things beyond my control.

Also changing the field into a property and use plain field.getter and field.setter are not feasible as this will break .filter(), .exclude() etc on the field, plus it will require a scheme change even if I changed field to _field and overrode the manager.

So, am I forced to override __setattr__ or is there a better way of doing this?

Community
  • 1
  • 1
Kimvais
  • 38,306
  • 16
  • 108
  • 142

3 Answers3

2

You could subclass the Field and override to_python.

class UnforgivingCharField(CharField):
    __metaclass__ = models.SubfieldBase

    def to_python(self, value):
        if not passes_my_test(value):
            raise Hell()
        return super(UnforgivingCharField, self).to_python(value)

This is used when the value is set and also during get_prep_value, etc., so it will catch invalid values when filtering.

More on this here. Note the line at the bottom of the linked section that tells us to_python will be called.

Edit: Just in case you happen to be using South, you will need to add some introspection rules if you implement custom model fields.

dokkaebi
  • 9,004
  • 3
  • 42
  • 60
0

See this django ticket:

https://code.djangoproject.com/ticket/3148

Also, see here for discussion:

Django model fields getter / setter

And this blog post:

http://www.b-list.org/weblog/2006/aug/18/django-tips-using-properties-models-and-managers/

Also note there is the option of using a custom manager that translates your filter kwargs for you, and using _name for fields, and making your own @name.setter @name.getter etc.

Community
  • 1
  • 1
Alex Hart
  • 1,663
  • 12
  • 15
0

Can you just define a function that provides the proper functionality and raises the correct error?

class YourModel(models.Model):

   def add_your_value(self, value):
       # check if value is correct
       # raise exception if it isn't
       # set correct property
dm03514
  • 54,664
  • 18
  • 108
  • 145
  • Yes I can, but that does not stop other people from doing `mymodelinstance.is_this_true_or_false = "banana"` – Kimvais Sep 28 '12 at 15:49