Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Re-architected code so that we track popularity of domains, updated a…

…nd added a domain-specific test
  • Loading branch information...
commit b86c88f2a8e09ad83b4c6616521eacefc3fb6ded 1 parent 8df1388
@aldeka authored
Showing with 54 additions and 33 deletions.
  1. +10 −14 shortcake/models.py
  2. +37 −6 shortcake/tests.py
  3. +7 −13 shortcake/views.py
View
24 shortcake/models.py
@@ -12,6 +12,9 @@ class Domain(models.Model):
domain = models.URLField(unique=True)
access_count = models.IntegerField(default=0)
+ def __unicode__(self):
+ return self.domain
+
def get_or_create_log(self,month):
''' returns a MonthLog object, either old or freshly created, for the given first-of-the-month date '''
try:
@@ -21,19 +24,20 @@ def get_or_create_log(self,month):
log.save()
return log
- @classmethod
+ @staticmethod
def extract_domain_from_url(url):
''' Takes a url, returns the url's domain '''
# take apart the domain
domain_parts = url.split('.')
# get the tld out of the last period-separated chunk
- tail_parts = domain_parts[-1].split('/',1)
+ tail = domain_parts.pop()
+ tail_parts = tail.split('/',1)
tld = tail_parts[0]
domain_parts.append(tld)
# put the string back together
return string.join(domain_parts, '.')
- @classmethod
+ @staticmethod
def get_or_create(url):
'''Returns a Domain object, either old or freshly created, based on a url'''
domain = Domain.extract_domain_from_url(url)
@@ -51,9 +55,6 @@ class Shurl(models.Model):
short_suffix = models.CharField(max_length=20,unique=True,**optional)
access_count = models.IntegerField(default=0)
creation_time = models.DateTimeField(auto_now_add=True)
- # this really shouldn't be optional
- # for now, it gets filled in for sure the first time get_url is called
- domain = models.ForeignKey(Domain, **optional)
def __unicode__(self):
return self.url
@@ -91,17 +92,12 @@ def is_nonunique(url):
return False
def get_url(self):
- '''Ups the access_count of the shurl and the relevant month's log before returning the url.
+ '''Ups the access_count of the shurl, the shurl's domain, and the relevant month's log before returning the url.
You probably want to use this method instead of accessing the url directly!'''
self.access_count += 1
self.save()
- try:
- d = self.domain
- except:
- self.domain = Domain.get_or_create(self.url)
- self.save()
- d = self.domain
+ d = Domain.get_or_create(self.url)
d.access_count += 1
d.save()
@@ -123,7 +119,7 @@ class MonthLog(models.Model):
access_count = models.IntegerField(default=0)
def __unicode__(self):
- return 'Log for ' + str(self.month) + ' of ' + self.domain
+ return 'Log for ' + str(self.month) + ' of ' + self.domain.domain
class Meta:
ordering = ['month']
View
43 shortcake/tests.py
@@ -1,7 +1,7 @@
from django.test import TestCase
from django.test.client import Client
-from shortcake.models import Shurl, MonthLog, first_of_the_month
+from shortcake.models import Shurl, Domain, MonthLog, first_of_the_month
import datetime
@@ -54,28 +54,59 @@ def setUp(self):
s.save()
s.assign_short_suffix()
- m = MonthLog(shurl=s)
+ d = Domain.get_or_create(s.url)
+
+ m = MonthLog(domain=d)
m.save()
past_time = datetime.date(2012,3,14)
- old_m = MonthLog(shurl=s, creation_date=past_time, month=first_of_the_month(past_time))
+ old_m = MonthLog(domain=d, creation_date=past_time, month=first_of_the_month(past_time))
old_m.save()
def test(self):
s = Shurl.objects.latest()
- m = s.monthlog_set.get(month=first_of_the_month())
- old_m = s.monthlog_set.get(month=datetime.date(2012,3,1))
+ d = Domain.get_or_create(s.url)
+ m = d.monthlog_set.get(month=first_of_the_month())
+ old_m = d.monthlog_set.get(month=datetime.date(2012,3,1))
self.assertEqual(0,s.access_count)
+ self.assertEqual(0,d.access_count)
self.assertEqual(0,m.access_count)
url = s.get_url()
# re-pull
s = Shurl.objects.latest()
- m = s.monthlog_set.get(month=first_of_the_month())
+ m = d.monthlog_set.get(month=first_of_the_month())
+ d = m.domain
self.assertEqual(url,s.url)
self.assertEqual(1,s.access_count)
self.assertEqual(1,m.access_count)
+ self.assertEqual(1,d.access_count)
self.assertEqual(0,old_m.access_count)
+class DomainTest(TestCase):
+ def setUp(self):
+ self.client = Client()
+ s = Shurl(url='http://www.test.com/a/b/c/')
+ s.save()
+ s.assign_short_suffix()
+
+ t = Shurl(url='http://www.test.com/another_dir/')
+ t.save()
+ t.assign_short_suffix()
+
+ s.get_url()
+ t.get_url()
+ t.get_url()
+
+ def test(self):
+ s = Shurl.objects.get(pk=1)
+ t = Shurl.objects.get(pk=2)
+ self.assertEqual(s.access_count,1)
+ self.assertEqual(t.access_count,2)
+
+ self.assertEqual(Domain.extract_domain_from_url(s.url),'http://www.test.com')
+
+ d = Domain.get_or_create(s.url)
+ self.assertEqual(d.access_count,3)
View
20 shortcake/views.py
@@ -31,32 +31,26 @@ def latest(request,count=100):
return HttpResponse(response)
def top_ten(request):
- '''Return the 10 short urls with the most hits this month'''
- # note: if fewer than ten urls have had *any* hits this month, it may return fewer than ten
+ '''Return the 10 domains with the most hits this month'''
+ # note: if fewer than ten domains have had *any* hits this month, it may return fewer than ten
this_month_logs = MonthLog.objects.filter(month=first_of_the_month())
popular_logs = this_month_logs.order_by('-access_count')[:10]
- shurls = []
+ domains = []
# this is kind of terrible, but whatev, it's only ten items
for log in popular_logs:
- shurls.append(log.shurl)
- response = json_serializer.serialize(shurls, ensure_ascii=False)
+ domains.append(log.domain)
+ response = json_serializer.serialize(domains, ensure_ascii=False)
return HttpResponse(response)
def forward(request,short_suffix):
'''Given the suffix of a short url, forwards us on to that short url's real url'''
n = convert_from_base_64(short_suffix)
shurl = get_object_or_404(Shurl,pk=n)
- # if the shurl hasn't had any hits yet this month, we'll need to create a MonthLog for it
- try:
- m = shurl.monthlog_set.filter(month=first_of_the_month())[0]
- except:
- m = MonthLog(shurl=shurl)
- m.save()
# get_url() updates the necessary access_counts and returns the url
return redirect(shurl.get_url())
def shurl_stats(request,short_suffix):
- '''Returns how many times a given short URL has been accessed'''
+ '''Returns how many times a given short URL has been accessed -- human readable'''
n = convert_from_base_64(short_suffix)
shurl = get_object_or_404(Shurl,pk=n)
return HttpResponse('URL ' + short_suffix + ' has been accessed ' + str(shurl.access_count) + ' time(s).')
@@ -68,4 +62,4 @@ def shurl_accesses(request,short_suffix):
return HttpResponse(str(shurl.access_count))
def api_documentation(request):
- return HttpResponse('<h1>Welcome to the shortcake API!</h1> <ul> <li>popular/ --> up to ten most popular (in terms of # of accesses) urls this month. May return fewer than 10 if fewer than 10 urls have any accesses</li> <li>latest/ --> last 100 shortened urls</li> <li>latest/(n) --> last n shortened urls</li> <li>(shortener)/accesses/ --> How many times the given shortener has been accessed</li></ul>')
+ return HttpResponse('<h1>Welcome to the shortcake API!</h1> <ul> <li>popular/ --> Up to ten most popular (in terms of # of accesses) shortened domains this month. May return fewer than 10 if fewer than 10 domains have had any accesses!</li> <li>latest/ --> Last 100 shortened urls.</li> <li>latest/(n) --> Last n shortened urls.</li> <li>(shortener)/accesses/ --> How many times the given shortener has been accessed.</li></ul>')

0 comments on commit b86c88f

Please sign in to comment.
Something went wrong with that request. Please try again.