Question

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=[]

Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top