I got form:
class SearchForm(Form):
owner = ModelMultipleChoiceField(queryset=User.objects.all(), required=False)
and after customizing get_queryset()
of related view it works as expected but I got objects without owner. I want to add additional new choice on top of the list (0,'Without owner')
so I could then filter only objects without owner.
How to add this option?
UPDATE:
I add the choice in form.__init__
and wrote custom clean method for it but if I choose added option something raises ValidationError
before getting to my clean method.I'm guessing I have to override form.is_valid
but I'm not sure how to do it so I can still use default is_valid method.
My code
def __init__(self, *args, **kwargs):
super(ClientListSearchForm, self).__init__(*args, **kwargs)
self.fields['owner'].choices = \
list(self.fields['owner'].choices)+[('0', 'n/a')]
def clean_owner(self):
logger.debug('CLEAN_OWNER:')
data = self.cleaned_data.get('owner')
logger.debug('data: %s' % data)
if data == 0:
logger.debug('Data zero - not assigned')
return data
users = User.objects.all()
if all(e in users for e in data):
logger.debug('Data in users - validating ok')
return data
else:
raise ValidationError('Incorrect owner')
I tried:
def is_valid(self):
try:
super(ClientListSearchForm, self).is_valid()
except ValidationError as e:
logger.debug('val error: %s' % e.args)
but it's nor validating nor caching exception
UPDATE2 Added custom validator
def userWithEmpty(value):
users = User.objects.values_list('pk').all()
v =list()
for va in value:
v.append(int(va))
u = list()
for us in users:
u.append(int(us[0]))
if not (all(e in u for e in v)or v ==0):
raise ValidationError('Invalid Value: %s' % value)
Is there a better way to convert every value in iterable than my for loops?
Didn’t post it as answer because there is a lot of place for improvement. Waiting for rants about what I'm doing wrong- and I will appreciate it all...
It STOPPED WORKING eee - there is something before validator from validators=[]
I ended up with other approach
class ModelMultipleChoiceWithEmptyField(ModelMultipleChoiceField):
def __init__(self, *args, **kwargs):
super(ModelMultipleChoiceWithEmptyField, self).__init__(*args, **kwargs)
self.choices = list(self.choices) + [('0', 'Brak')]
def clean(self, value):
if self.required and not value:
raise ValidationError(self.error_messages['required'], code='required')
if value == [u'0']:
return value
return super(ModelMultipleChoiceWithEmptyField,self).clean(value)
It's much cleaner and it works. Fell free to reuse and improve