How to access the value of a field that failed validation

36 views
Skip to first unread message

Noel Duffy

unread,
Jan 1, 2023, 7:27:01 PM1/1/23
to django...@googlegroups.com
I'm new to Django, though not to programming. I'm using Django 4.1.4 on
AlmaLinux 9.

My question is this. Is it possible to access a ModelForm field's value
if that form field failed validation?

I'm writing a small ticketing system for a helpdesk to handle spam
reports. Users submit spam messages which the system will then process.
I'm using a ModelForm, and the database schema specifies that the spam
message is unique. That is, each spam message can be reported only once,
so there's just one ticket but possibly many different actions taken
depending on what's in the spam.

This is the model:

class AbuseReport(models.Model):
report_date = models.DateTimeField(auto_now_add=True)
report_subject = models.CharField(max_length=255)
report_msgid = models.CharField(max_length=255, unique = True)
report_spam_text = models.TextField(unique = True)
def __str__(self):
return report_subject

class Meta:
ordering = ['-report_date']

Now, the problem is that a spam message will fail form validation in the
form.is_valid call if the spam message fails the "unique" constraint.
Why is this a problem? Because I want to get my hands on the spam
message if it's already in the DB so that instead of just re-showing my
form with an error message saying the spam already exists, I want to
redirect to the existing ticket. But so far I've not been able to figure
out how to do this, and when I dump the contents of the form in
debugging, the spam message just isn't there.

I should add that the ModelForm only creates a field for the
report_spam_text field. I.e,

class AbuseReportForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ModelForm, self).__init__(*args, **kwargs)

def clean(self):
[...]

class Meta:
model = AbuseReport
fields = ['report_spam_text']
widgets = {'report_spam_text':
Textarea(attrs={
'rows': 20,
'class':'textarea',
'placeholder':'Paste spam with full headers here..'
}),}


This is what my view looks like (stripped down for simplicity):

def spamsubmit(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the
request:
form = AbuseReportForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
[.....]
else:
## show the form again with errors displayed
## if spam already exists this is what gets run.
return render(request, 'abuse/spam_form.html',{'form':form})

As I understand it, fields aren't bound to data until is_valid is
called, and if is_valid fails then only fields that didn't fail validity
go into cleaned_data. But it seems everything else is lost. But I'm not
100% sure about this and this is why I'm asking.



Alex Sonar

unread,
Jan 2, 2023, 8:34:59 AM1/2/23
to Django users
Hi Noel!
Have you looked at the problem in context CSRF Protection?
Please check it out
It might be as a solution...

Noel Duffy

unread,
Jan 2, 2023, 4:00:23 PM1/2/23
to django...@googlegroups.com
On 3/01/23 02:21, Alex Sonar wrote:
> Hi Noel!
> Have you looked at the problem in context CSRF Protection?
> Please check it out
>
> - How to use Django’s CSRF protection
> https://docs.djangoproject.com/en/4.1/howto/csrf/
>
> It might be as a solution...

I don't see how this helps. I want to access a field value even if the
call to form.is_valid fails. CSRF protection, which is on by default,
doesn't affect this in any way that I can see.



Jason

unread,
Jan 3, 2023, 7:54:54 AM1/3/23
to Django users
you'll need to implement custom validators to override the default `ValidationError` message for the fields.  some fields include this functionality by default, ie DecimalField (https://github.com/django/django/blob/main/django/forms/fields.py#L419-L428), others don't

Clive Bruton

unread,
Jan 15, 2023, 7:41:45 AM1/15/23
to django...@googlegroups.com
If you print:

dir(form_instance)

You'll get the methods available to the form. From memory, amongst
these you will find "data" and "initial", I think that "data"
contains the information submitted in the form action. So, to show that:

print(form.data)


-- Clive
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to django-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/
> d/msgid/django-users/tot7hm%2412qg%241%40ciao.gmane.io.
>

Reply all
Reply to author
Forward
0 new messages