Opened 3 weeks ago

Closed 3 weeks ago

Last modified 3 weeks ago

#36886 closed New feature (wontfix)

URLField max_length cannot take advantage of supports_unlimited_charfield in DB backend

Reported by: Joel D Sleppy Owned by: Joel D Sleppy
Component: Database layer (models, ORM) Version: 6.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: yes
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When using a DB backend that supports_unlimited_charfield (postgres, sqlite), a CharField can omit max_length and allow arbitrarily long values in the database. However URLField, which inherits from CharField, forces the developer to pick a maximum length. For example, this model class:

class Thing(models.Model):
    chars = models.CharField()
    url = models.URLField()

Creates this table in postgres:

                                 Table "public.app_thing"
 Column |          Type          | Collation | Nullable |             Default              
--------+------------------------+-----------+----------+----------------------------------
 id     | bigint                 |           | not null | generated by default as identity
 chars  | character varying      |           | not null | 
 url    | character varying(200) |           | not null | 

And trying to set url = models.URLField(max_length=None) does not get recognized as a change by makemigrations.

URLs can get quite long and it's an inconvenience to pick a maximum length (and to defensively code against the possibility of it being violated). I'd like to work on this improvement myself if there's any appetite for it.

Possible changes:

  • For backwards compatibility, continue to default max_length to 200 but allow specifying None to have an unbounded field.
  • Break backwards compatibility, changing behavior to match that of CharField.

Change History (3)

comment:1 by Joel D Sleppy, 3 weeks ago

Needs documentation: set
Needs tests: set

comment:2 by Natalia Bidart, 3 weeks ago

Resolution: wontfix
Status: assignedclosed
Type: UncategorizedNew feature

Hello Joel! Thank you for your ticket. I think I understand where you are coming from, but Django provides general purpose, conservative primitives. URLField is not just a thin alias for CharField; it is a higher level abstraction with semantic expectations, including validation and reasonable defaults. Requiring an explicit max_length is part of that contract.

While URL length limits are not formally standardized, URLs do need practical bounds. Allowing unbounded URL storage meaningfully increases risk surface. Extremely long URLs are a known vector for denial of service and resource exhaustion issues across layers (application, logging, middleware, and more), and multiple historical CVEs across frameworks and servers have been rooted in unbounded or insufficiently constrained string inputs.

The existence of supports_unlimited_charfield at the database backend level does not imply that all higher level field types should opt into unbounded storage. CharField is intentionally low level. URLField intentionally is not. From an API design perspective, allowing max_length=None for URLField would blur the distinction between CharField and URLField, weaken Django's defensive defaults, and introduce subtle backwards compatibility and security review concerns for limited practical gain. Developers who genuinely need unbounded URL-like strings can already model that explicitly using CharField with specific validators.

Given these considerations, the requirement for an explicit maximum length on URLField is intentional and appropriate, even on backends that support unlimited character fields.

comment:3 by Joel D Sleppy, 3 weeks ago

Cheers Natalia, thanks for the response. I can't say I understand fully, but I'll keep building my intuition on these things.

Note: See TracTickets for help on using tickets.
Back to Top