Currently, Django’s URLField is tied to the default behavior of URLValidator, which validates URLs based on a fixed set of schemas or a custom list passed directly to the validator. While it is possible to override the validator for a field, this approach introduces redundancy and can lead to unintended double validation issues.
To improve flexibility and usability, we propose adding a schema parameter directly to URLField. This allows developers to declaratively define the URL schemes they accept without having to manually replace the default validator or inherit or modify the field class.
Current Behavior
The existing URLField relies on default_validators containing a single URLValidator. While developers can supply a custom validator, this often results in double validation if the new validator is added alongside the default one. For example:
# Current workaround
secure_url = models.URLField(validators=[validators.URLValidator(schemes=["https"])])
This works for restricting schemes to https, but extending schemes (e.g., custom-scheme://, mailto://) becomes problematic. The default_validators and the passed validators are combined, causing the same validation to run twice unnecessarily.
Proposed Solution
Introduce a schemes parameter in URLField, enabling developers to directly define valid schemes for the field:
# Allow only http and https
url = models.URLField(schemes=["http", "https"])
# Allow any scheme (default behavior)
url = models.URLField()
# Example including custom schemes
custom_url = models.URLField(schemes=["custom-scheme", "mailto"])
If the schemes parameter is provided, the field dynamically configures its URLValidator with the specified schemes. If no schemes parameter is provided, the default behavior (all schemes allowed) remains unchanged.
I look forward to hearing the community’s thoughts on this proposal. Thank you!