From db1524fd64e8b5c0f43cfed7643034ee764f55fd Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Sun, 27 Feb 2011 12:31:06 -0600 Subject: Auto map the protocol URL field And perform better validation when doing so. Signed-off-by: Dan McGee --- mirrors/admin.py | 20 ++++++++++++++++---- mirrors/models.py | 14 +++++++++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/mirrors/admin.py b/mirrors/admin.py index 6990cca2..f6a72cf0 100644 --- a/mirrors/admin.py +++ b/mirrors/admin.py @@ -1,4 +1,5 @@ import re +from urlparse import urlparse, urlunsplit from django import forms from django.contrib import admin @@ -9,15 +10,26 @@ class MirrorUrlForm(forms.ModelForm): class Meta: model = MirrorUrl def clean_url(self): + # is this a valid-looking URL? + url_parts = urlparse(self.cleaned_data["url"]) + if not url_parts.scheme: + raise forms.ValidationError("No URL scheme (protocol) provided.") + if not url_parts.netloc: + raise forms.ValidationError("No URL host provided.") + if url_parts.params or url_parts.query or url_parts.fragment: + raise forms.ValidationError( + "URL parameters, query, and fragment elements are not supported.") # ensure we always save the URL with a trailing slash - url = self.cleaned_data["url"].strip() - if url[-1] == '/': - return url - return url + '/' + path = url_parts.path + if not path.endswith('/'): + path += '/' + url = urlunsplit((url_parts.scheme, url_parts.netloc, path, '', '')) + return url class MirrorUrlInlineAdmin(admin.TabularInline): model = MirrorUrl form = MirrorUrlForm + readonly_fields = ('protocol',) extra = 3 # ripped off from django.forms.fields, adding netmask ability diff --git a/mirrors/models.py b/mirrors/models.py index e070b1cd..b763fb63 100644 --- a/mirrors/models.py +++ b/mirrors/models.py @@ -1,4 +1,7 @@ from django.db import models +from django.core.exceptions import ValidationError + +from urlparse import urlparse TIER_CHOICES = ( (0, 'Tier 0'), @@ -50,11 +53,20 @@ class MirrorProtocol(models.Model): class MirrorUrl(models.Model): url = models.CharField(max_length=255) - protocol = models.ForeignKey(MirrorProtocol, related_name="urls") + protocol = models.ForeignKey(MirrorProtocol, related_name="urls", + editable=False) mirror = models.ForeignKey(Mirror, related_name="urls") has_ipv4 = models.BooleanField("IPv4 capable", default=True) has_ipv6 = models.BooleanField("IPv6 capable", default=False) + def clean(self): + try: + # Auto-map the protocol field by looking at the URL + protocol = urlparse(self.url).scheme + self.protocol = MirrorProtocol.objects.get(protocol=protocol) + except Exception as e: + raise ValidationError(e) + def __unicode__(self): return self.url -- cgit v1.2.3-55-g3dc8