views:

57

answers:

4

I have a field that has a max_length set. When I save a model instance, and the field's value is greater than max_length, Django enforces that max_length at the database level. (See Django docs on models: http://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.CharField.max_length)

However, since I am using Postgres, I receive a DatabaseError exception like this:

DatabaseError: value too long for type character varying(1000)

I would prefer to instead auto-truncate the value (so I don't have an exception). Now, I can do this manually, but what I would really want is to have all of my models auto-truncate the value. (Not necessarily intelligently. Just cutting it off at the 999th character is fine.)

Should I just write a custom class that imports from models.Model and override the save() method, looping through each _meta.field, checking for the max_length, and then truncating? That seems inelegant and there must be a better way.

A: 

Why don't you used ModelForm. ModelForm enforces a validation, setting its default max_length to model field's max_length property, and raising proper validation error when form.is_valid() is called. That way you don't have to save the form, until form is validated.

Or, if you want to silently pass the validation and truncate suits best to you, write a simple django form, and write a clean method that truncates input string to the max_length and return stripped data. Take data from form.cleaned_data after form is validated and save the object.

All considering the fact, Forms are designed to validate data before going to DB.

simplyharsh
+2  A: 

Why don't you use a TextField? From the manual:

For large amounts of text, use TextField.

Frank Heikens
Yeah, looking at what you've written, if you want it cut off at the 999th character that suggests to me that a TextField might be a better choice.
Jordan Reiter
+1  A: 

You could create a custom field that auto-truncates the field (I think this code should work, but double-check it):

class TruncatingCharField(models.CharField):
    def get_prep_value(self, value):
        value = super(TruncatingCharField,self).get_prep_value(value)
        if value:
            return value[:self.max_length]
        return value

Then, instead of using models.CharField in your models.py file, you'd just use TruncatingCharField instead.

get_prep_value prepares the value for a field for insertion in the database, so it's the ideal place to truncate.

Jordan Reiter
A: 

That seems inelegant and there must be a better way.

The only reason the truncate behavior ever happens in the first place is because of MySQL's failure to adhere to the SQL Standard. The throwing of an exception is the correct response when attempting to INSERT a string into a VARCHAR field that is not wide enough to hold it. MySQL truncates and inserts instead.

If you want to silently corrupt your data, then you'll have to do it manually somehow--PostgreSQL will never do it for you.

Matthew Wood