Why using validators=[URLValidator] when defining a model CharField doesn't make it check for URL-validity upon saving the corresponding ModelForm?

Question:

app.models.py:

from django.core.validators import URLValidator
from django.db import models

class Snapshot(models.Model):
    url = models.CharField(max_length=1999, validators=[URLValidator])

app.forms.py:

from django import forms
from .models import Snapshot

class SnapshotForm(forms.ModelForm):
    class Meta:
        model = Snapshot
        fields = ('url',)

app.views.py:

from django.http import HttpResponse
from .forms import SnapshotForm

def index(request):
    snapshot_form = SnapshotForm(data={'url': 'not an URL!'})

    if snapshot_form.is_valid():
        snapshot_form.save()

    return HttpResponse("")

Why does it save ‘not an URL!’ into DB, despite the fact that it ain’t a valid URL?!

What is the right way to incorporate URLValidator?

Asked By: chakmeshma

||

Answers:

You’ve specified the validators for your field like so: validators=[URLValidator]. This is incorrect because the validators argument takes in a list of callables that perform the validation. In this case even though URLValidator is callable but that’s actually the __init__ method of the class being called. You need to pass an instance of the class for it to work properly:

# Note the brackets after URLValidator to instantiate the class
url = models.CharField(max_length=1999, validators=[URLValidator()])

Better yet since you want to take input a URL you should simply use the URLField class for your field:

url = models.URLField(max_length=1999)
Answered By: Abdul Aziz Barkat