Django--URLField issues around Absolute vs. Relative URLs
I have a URLField which is optional in my model. I've also made it optional in the ModelForm. The problem is that I do ONLY want the form to generate absolute URLs. I had thought that the URLField automatically does so but it's not working for me at present.
So, to overcome the problem, I've decided to override the save() method on the model. I wanted to override the clean_field() method on the modelform 开发者_运维问答field; however, it appears as though you cannot set a clean_field method on a form field with "required=False".
def save(self,*args, **kwargs):
if self.url:
if not self.url.startswith('http://'):
self.url='http://' + self.url
super(Post, self).save(*args, **kwargs)
Am I missing something here? Is this perfectly acceptable?
If your model has a field called url
and you define a clean_url() method on your ModelForm, it should get called when url is present regardless of whether or not its an optional field. By performing validation in the save method, you're mixing concerns and breaking the design of the ModelForm class. Validation should always be considered complete after a successful call to is_valid().
But aside from that, you've got another problem here.
Remember, a URL is written scheme://host:port/absolute_path
. The absolute path is encoded into the URL, but a URL itself is more than just an absolute path.
The problem with relative paths is determining what they're relative to. Absolute paths start with a leading '/' and they are always relative to the server or filesystem root. Relative paths are relative to the current active resource. The problem here is, what's the current active resource? Further, making save() aware of (and therefore require) this information is a broken architecture for sure.
Aside from that, your code above will break on alternative schemes (https), it doesn't insert the host into the URL, and for paths not relative to the root, how do we know what they're relative to?
I think you had the correct strategy to start. Only allow input of absolute paths and URLs, not relative paths. Have your ModelForm replace absolute paths with valid URLs. To do this, take another look at the documentation for the clean() methods on ModelForm, and if you have problems getting that to work, open a new question specific to that problem.
精彩评论