Problem appending to ManyToMany form field when cleaning data
Just moved from Django 1.00 to 1.30 and I'm suddenly getting an error during form validation:
A开发者_JAVA百科ttributeError: 'QuerySet' object has no attribute 'append'
The code is below. While cleaning the list of coordinators specified by the user in the form, I want to include all super-users as well.
The problem seems to be that the cleaned_data.get() call is returning a QuerySet. I thought it returned an object representing the field type. As I said above, this code used to work in 1.0, but maybe that was an accident.
Can someone tell me what cleaned_data.get is returning in this case and how I can add other values to it?
Thanks.
class Party(models.Model):
coordinators = models.ManyToManyField( 'PersonProfile', blank=True, related_name='event_coordinator_set', help_text='' )
class PartyForm(ModelForm):
class Meta:
model = Party
def __init__( self, *args, **kwargs ):
super( PartyForm, self ).__init__(*args, **kwargs)
self.fields['coordinators'].queryset = PersonProfile.objects.exclude( user__is_superuser=1 )
def clean_coordinators( self ):
coordinators = self.cleaned_data.get( 'coordinators', '' )
superuser_list = PersonProfile.objects.filter( user__is_superuser=1 )
for superuser in superuser_list:
coordinators.append( superuser )
return coordinators
Try the following:
from django.db.models import Q
def clean_coordinators( self ):
coordinators = self.cleaned_data.get( 'coordinators', '' )
if coordinators:
return PersonProfile.objects.filter(
Q(pk__in=coordinators) | Q(user__is_superuser=1)
)
else:
return PersonProfile.objects.filter(user__is_superuser=1)
As soon as you found out it was a QuerySet
, you could have just turned the queryset into a list and leave the rest of your code intact... coordinatiors = list(myqueryset)
, but I would recommend Thierry's solution.
Anyho, you're right: I looked at django 1.0, and ModelMultipleChoiceField
used to return a list. Now, it returns a QuerySet
.
Django 1.0 ModelMultipleChoiceField.clean()
final_values = []
for val in value:
try:
obj = self.queryset.get(pk=val)
except self.queryset.model.DoesNotExist:
raise ValidationError(self.error_messages['invalid_choice'] % val)
else:
final_values.append(obj)
return final_values
Django 1.3 ModelMultipleChoiceField.clean()
for pk in value:
try:
self.queryset.filter(**{key: pk})
except ValueError:
raise ValidationError(self.error_messages['invalid_pk_value'] % pk)
qs = self.queryset.filter(**{'%s__in' % key: value})
pks = set([force_unicode(getattr(o, key)) for o in qs])
for val in value:
if force_unicode(val) not in pks:
raise ValidationError(self.error_messages['invalid_choice'] % val)
# Since this overrides the inherited ModelChoiceField.clean
# we run custom validators here
self.run_validators(value)
return qs
精彩评论