I'm using a ModelMultipleChoiceField to allow users to select certain model objects to delete. It works fine when a single object is selected, but when multiple objects are selected then a validation error is triggered: "Ensure this value has at most 50 characters". The 50 character limit is from the underlying model's max_length attribute. I'm not sure why this validation is happening at all since I am selecting existing model objects, and even less sure why they are combining the character lengths of all my selections instead of validating each selection individually. I've also noticed that approximately 20 extra characters are being counted for each object selected when totalling the character length. Any help is appreciated.
Here is my code:
Model:
class Template(models.Model):
# Relationships
user = models.ForeignKey("users.CustomUser", on_delete=models.CASCADE)
# Fields
name = models.CharField(max_length=50)
description = models.TextField(max_length=250)
docx_file = models.FileField(("DOCX File"),
upload_to=user_directory_path,
validators=[FileExtensionValidator(allowed_extensions=['docx'])])
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
def __str__(self):
return self.name
Form:
class TemplateChoiceDelete(forms.ModelForm):
name = forms.ModelMultipleChoiceField(queryset=Template.objects.all())
class Meta:
model = Template
fields = ['name']
# Limit results to templates owned by the current user
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(TemplateChoiceDelete, self).__init__(*args, **kwargs)
self.fields['name'].queryset = Template.objects.filter(user=user)
View: (ignore the filter code, that is a work in progress relating to another feature)
def manage_templates(request):
f = TemplateFilter(request.GET, queryset=Template.objects.filter(user=request.user))
if request.method == 'GET':
choice_form = TemplateChoiceDelete(request.GET, user=request.user)
print(choice_form)
if choice_form.is_valid():
choice_form.cleaned_data['name'].delete()
else:
form = TemplateChoiceDelete
return render(request, 'docs/manage_templates.html', {'filter': f, 'choice_form': choice_form})
Template: (again, please ignore the code relating to filters)
{% block content %}
<p> <b> Search </b> </p>
<form method="get">
{{ filter.form.as_p }}
<input type="submit" value="Search" />
</form>
{% for obj in filter.qs %}
{{ obj.name }} | {{ obj.description }}<br />
{% endfor %}
<br>
<p><b> Delete Templates </b></p>
<form method="GET">
{{ choice_form.as_p }}
<input type="submit" onclick="return confirm('Are you sure? This will delete the selected template(s)')" value="Delete">
</form>
{% endblock %}
This is not a
ModelForm
, if you use aModelForm
, it will of course "inherit" certain validators from the model. This is a simpleForm
, so:A
ModelForm
is aForm
that is tailored towards a certain model to create or update a model instance, not to edit items that have "something to do" with that model.