Opened 17 years ago
Closed 14 years ago
#6092 closed (wontfix)
URL and email fields need to allow custom validators
Reported by: | Jacob | Owned by: | floguy |
---|---|---|---|
Component: | Core (Other) | Version: | dev |
Severity: | Keywords: | ||
Cc: | joel@…, listuser@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
See #3989 and #6019 -- in both cases, people want to define "email" or "URL" a bit differently than Django does by default. In both cases, changing the default isn't the answer since that'll just make new people unhappy with the new defaults.
So, I should be able to do something like this:
rfc2822pattern = re.compile(...) # ... email = models.EmailField(pattern=rfc2822pattern)
That's just a strawman proposal, of course -- I'm not sure I like that syntax.
Attachments (4)
Change History (14)
comment:1 by , 17 years ago
comment:2 by , 17 years ago
Has patch: | set |
---|---|
Needs documentation: | set |
Owner: | changed from | to
Status: | new → assigned |
I have created an initial patch for this, which makes models.EmailField, models.URLField, (new)forms.EmailField, (new)forms.URLField all take a pattern keyword argument.
This pattern kwarg can be either a string or a compiled regular expression.
There are also regression tests for the newforms modifications.
by , 17 years ago
Initial patch to add pattern keyword argument to several model and form fields.
comment:3 by , 17 years ago
Needs documentation: | unset |
---|
comment:4 by , 17 years ago
Triage Stage: | Unreviewed → Ready for checkin |
---|
comment:5 by , 17 years ago
Patch needs improvement: | set |
---|---|
Triage Stage: | Ready for checkin → Accepted |
There are a few problems with the code patch that need work here.
- The
get()
method on a dictionary returns None by default; no need to specify it. - Don't write
== None
or!= None
. Instead, useis
andis not
to compare withNone
, since there's only oneNone
object in Python. However, this is moot here anyway, since you might as well just check for "truthiness" --if pattern: ...
-- rather than all the None checks. It's slightly more idiomatic which means people won't be caught wondering why we aren't using the obvious construct. - Let's simplify the internals a bit by saying that people should pass in a reg-exp object here (so the parameter should probably be called something other than "pattern"). Then you can just use duck-typing assumptions and you don't need to check the type or anything. Simply call
.match()
on the passed in object when we need it. That will remove a bunch of if-blocks. Bear in mind that this is for a bit of a corner case, so it's not going to be a huge burden to ask them to callre.compile
once first.
I don't see a huge advantage in allowing both reg-exp objects *and* strings and by choosing the reg-exp approach, we allow the user to pass in anything that has a match()
method, since we only use that, which could be something more complex than a reg-exp if they really wanted it.
by , 17 years ago
Attachment: | 6092.2.diff added |
---|
Updated patch to be more idiomatic Python and to require a compiled regular expression object.
comment:6 by , 17 years ago
Cc: | added |
---|
comment:8 by , 15 years ago
#11551 has a simple workaround that addresses this. The patch was declined but it can be used if necessary.
comment:9 by , 14 years ago
This ticket hasn't seen much attention lately and I question how relevant this ticket is given the changes in the 1.2 release allowing pluggable validators. http://docs.djangoproject.com/en/1.2/ref/validators/
Both the default email and url validation logic can be overridden with a sub-class of the appropriate field which I would argue as more DRY than a new kwarg. An example of the email field overrides (without the actual regex) is given below:
import re from django import forms from django.core.validators EmailValidator from django.db import models from django.utils.translation import ugettext_lazy as _ rfc2822pattern = re.compile(...) validate_email = EmailValidator(rfc2822pattern, _(u'Enter a valid e-mail address.'), 'invalid') class RFC2822EmailFormField(forms.EmailField) default_validators = [validate_email] class RFC2822EmailField(models.EmailField) default_validators = [validate_email] def formfield(self, **kwargs): defaults = { 'form_class': RFC2822EmailFormField, } defaults.update(kwargs) return super(RFC2822EmailField, self).formfield(**defaults)
comment:10 by , 14 years ago
Resolution: | → wontfix |
---|---|
Status: | assigned → closed |
I agree with mlavin. I think validators make this feature unnecessary.
Note that parsing an email address with a regex may be considered an abuse of the regex system, and people previous complained that being able to parse all valid email addresses would need an unbearbly complex and hard to debug regex. Email addresses are a full language, and there's a reason they are defined in ABNF. They should be parsed with a real parser, IMHO.