Skip to content
This repository has been archived by the owner on Feb 11, 2020. It is now read-only.

Commit

Permalink
adding proper validation that short_url is unique for this site
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmin committed Nov 6, 2011
1 parent 8a1ffdb commit 92b427a
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
20 changes: 19 additions & 1 deletion clktc/links/models.py
@@ -1,8 +1,14 @@
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core.exceptions import ValidationError
from django.db import models

# Create your models here.

class LinkWithShortUrlAlreadyExistsForSite(ValidationError):
def __init__(self):
super(LinkWithShortUrlAlreadyExistsForSite, self).__init__({
'short_url': ["Link with this short URL already exists for this site. Please try another one."]
})

class Link(models.Model):
destination_url = models.URLField("Destination", max_length=255, blank=False, verify_exists=False)
Expand All @@ -17,7 +23,19 @@ class Meta:
def url(self):
return "http://%s/%s" % (self.site.domain, self.short_url)

def is_unique(self, matching):
if not len(matching):
return True
elif self.pk:
if len(matching) == 1:
other = matching.get()
return other.pk == self.pk

def save(self, *args, **kw):
if self.short_url and self.site_id:
matching = Link.objects.filter(short_url=self.short_url, site=self.site)
if not self.is_unique(matching):
raise LinkWithShortUrlAlreadyExistsForSite()
self.full_clean()
super(Link, self).save(*args, **kw)

2 changes: 1 addition & 1 deletion clktc/links/tests/test_models.py
Expand Up @@ -47,7 +47,7 @@ def test_site_and_short_url_are_unique_together(self):
Model.save(l1)
Model.save(l2)

@raises_regexp(ValidationError, 'Link with this Short URL and Site already exists')
@raises_regexp(ValidationError, 'Link with this short URL already exists for this site. Please try another one.')
def test_site_and_short_url_are_unique_together(self):
Link(destination_url = "http://example.com", short_url = "foobarbaz", site = self.site).save()
Link(destination_url = "http://example.com", short_url = "foobarbaz", site = self.site).save()
Expand Down
8 changes: 7 additions & 1 deletion clktc/links/tests/test_views.py
Expand Up @@ -64,6 +64,12 @@ def test_adding_a_link_without_short_url(self):
response = self.client.post('/l/add/', {"destination_url" : EXAMPLE_URL, "short_url" : ""})
self.assertFormError(response, 'form', 'short_url', u'This field is required.')

def test_adding_a_link_with_duplicate_short_url(self):
link = given_a_link(self.site, user=self.user)
response = self.client.post('/l/add/', {"destination_url" : "http://foo.bar/baz", "short_url": link.short_url})
self.assertFormError(response, 'form', 'short_url', u'Link with this short URL already exists for this site. Please try another one.')


class EditLinkTest(ViewBaseTest):
def test_edit_link_returns_404_if_current_owner_does_not_match(self):
link = given_a_link(self.site)
Expand All @@ -84,7 +90,7 @@ def test_save_on_edit_link_updates_link_with_new_details(self):

def test_save_on_edit_link_redirects_to_all_links(self):
link = given_a_link(self.site, user=self.user)
response = self.client.post("/l/edit/%s" % link.pk, {"destination_url" : "http://example.org", "short_url" : "example2"})
response = self.client.post("/l/edit/%s" % link.pk, {"destination_url" : "http://example.org"})
self.assertRedirects(response, ALL_LINKS)

class VisitLinkTest(ViewBaseTest):
Expand Down
8 changes: 6 additions & 2 deletions clktc/links/views.py
@@ -1,5 +1,6 @@
# Create your views here.
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ValidationError
from django.http import HttpResponseNotAllowed, HttpResponseNotFound
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template.context import RequestContext
Expand All @@ -23,8 +24,11 @@ def add_link(request):
link = form.save(commit=False)
link.site = request.site
link.user = request.user
link.save()
return redirect(get_all_links)
try:
link.save()
return redirect(get_all_links)
except ValidationError as ve:
form._update_errors(ve.message_dict)
else:
form = AddLinkForm()
return render_to_response("links/add.html", RequestContext(request, {'form': form}))
Expand Down

0 comments on commit 92b427a

Please sign in to comment.