#22959 closed Cleanup/optimization (fixed)
Document that custom validator must be comparable to prevent infinite migrations
Reported by: | Owned by: | Markus Holtermann | |
---|---|---|---|
Component: | Documentation | Version: | 1.7-rc-1 |
Severity: | Normal | Keywords: | migrations |
Cc: | Areski Belaid, info+coding@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I'm using a custom validator with a proper deconstruct on a TextField, it's intended to control the min and max number of words in the field. If I run python manage.py makemigrations over and over again it keeps generating the same migration related to changes on that text field, changes that do not exist.
Change History (11)
comment:1 by , 10 years ago
Component: | Migrations → Documentation |
---|---|
Summary: | Custom validator in TextField → Document that custom validator must be comparable to prevent infinite migrations |
Triage Stage: | Unreviewed → Accepted |
Type: | Uncategorized → Cleanup/optimization |
comment:2 by , 10 years ago
I have been trying to reproduce this problem without luck!
Could you share a code sample where this could be reproduced?
This is how I tried to reproduce it:
from django.db import models from django.core.exceptions import ValidationError def validate_textlimit20chars(value): if len(value) > 20: raise ValidationError('%s is not an even number' % value) class MyModel(models.Model): name = models.CharField(max_length=32) text20_field = models.TextField(default="", validators=[validate_textlimit20chars])
comment:3 by , 10 years ago
Cc: | added |
---|
comment:4 by , 10 years ago
Try a class-based validator like the ones for which an __eq__
method was added in the commit I linked in comment 1.
comment:5 by , 10 years ago
I'm trying to figure out how to make the class-based validator works, no luck: https://gist.github.com/areski/b9e293ad34d2b6845958
anyone can provide a working example?
comment:6 by , 10 years ago
Here's the original validator I used to get to know the problem (of course, by the time I discovered it there was no cmp)
class LimitWordsValidator: def __init__(self, limit, upper=True): self.limit = limit self.upper = upper def __cmp__(x, y): return cmp(x.limit, y.limit) or cmp(x.upper, y.upper) def __call__(self, value): words = len(strip_tags(value).split()) args = { 'limit': self.limit, 'current': words, } if self.upper and words > self.limit: raise ValidationError(_('You cannot exceed %(limit)s words, you have %(current)s.') % args) if not self.upper and words < self.limit: raise ValidationError(_('You need at least %(limit)s words, you have %(current)s.') % args) def deconstruct(self): return ( 'common.validators.LimitWordsValidator', [self.limit], {'upper': self.upper}, )
comment:8 by , 10 years ago
Cc: | added |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:9 by , 10 years ago
Has patch: | set |
---|
I added a pull request with documentation updates: https://github.com/django/django/pull/3271
comment:10 by , 10 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
This probably isn't an issue with Django itself but rather with your validator; they need to be comparable as in a68f32579145dfbd51d87e14f9b5e04c770f9081. However, we could add some docs about this since it will probably be a FAQ.