Search code examples
pythondjangodjango-modelsdjango-formsdjango-validation

How to change the default error messages displayed by Django forms


I have created a form in Django which has a charfield with max_length=255 as follows:

task = models.CharField(max_length= 255)

Now I want to let the user know how many characters he has typed if he exceeds the 255 characters limit, so I did the following

if form.is_valid():
    #some code
else:
    messages.info(request,(form.errors.get("task").as_text()))

now suppose if I type 445 characters in the form field and submit then by default I am getting the following error message:

* Ensure this value has at most 255 characters (it has 445).

but instead, I want to change this message to:

Error: maximum length limit is 255 characters (it has 445).

So I tried the following:

class ListForm(ModelForm):
    class Meta:
        model = ListModel
        fields = ["task", "status"]

        error_messages = {
            'task': {
                'max_length': ("Error: maximum length limit is 255 characters"),
                
            },
        }

Now the message has been changed to:

* Error: maximum length limit is 255 characters.

My Problem:

  1. I don't want the * which is being displayed in front of the messages
  2. I was not able to capture the number of characters the user has typed, which was being displayed in the default message i.e. (it has 445)

What can I do to print Error: maximum length limit is 255 characters (it has 445). instead of * Error: maximum length limit is 255 characters.?


Solution

  • I don't want the * which is being displayed in front of the messages

    The problem as you finally came to the conclusion (in the comments) is in

    form.errors.get("task").as_text()
    

    This sends to the client a <ul> HTML element and not the plain text. So what you can do, to solve this problem and your other problem is simply check if max_length can be found in form.errors and use your own string. The following should go in your view after form.is_valid has been called

    # After this point form.is_valid() has been called
    if "max_length" in form.errors:
        task = request.POST.get("task") # Get the text that was entered in `task`
        length_of_task = len(task) 
        # Simply send your own message
        messages.info(request, f"Error: maximum length limit is 255 characters (it has {length_of_task}).")
    

    Note a few things here

    • Accessing the data by using request.POST.get

    @SaeX Pointed out that you can use self.cleaned_data.get to get The data that was sent in the POST request. While this is true, it only works if form.is_valid has returned true. You can find out more here.

    • What if I want to catch multiple errors and use a dictionary

    You can still use a dictionary but for values you will have to use functions. Something like the following

    def handle_max_length(data):
        datalen = len(data) > 255 # Do your stuff
        
    def handle_some_other_error(data):
        pass 
    
    errors = {
        'max_length' : handle_max_length,
        'some_other_error': handle_some_other_error
    }
    
    def myView(request):
        # ... code
        form = MyForm()
        if not form.is_valid():
            for field in form.errors:
                field_value = request.POST.get(field)
                for error in field:
                    messages.info(
                        request, errors.get(error)(field_value) # Getting the function and calling it with the data
                    )