Sort of works now

This commit is contained in:
Jonathan Cremin 2015-01-17 23:54:26 +00:00
parent 593f3e6d1c
commit 5972323cc1
15 changed files with 453 additions and 6 deletions

0
links/__init__.py Normal file
View file

3
links/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View file

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='Link',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('link', models.URLField(max_length=2048)),
('base62', models.CharField(max_length=64, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('clicks', models.IntegerField(default=0)),
('ip', models.GenericIPAddressField(null=True)),
],
options={
},
bases=(models.Model,),
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('links', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='link',
name='id',
field=models.AutoField(serialize=False, primary_key=True),
preserve_default=True,
),
]

View file

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('links', '0002_auto_20150117_2248'),
]
operations = [
migrations.RemoveField(
model_name='link',
name='base62',
),
migrations.AlterField(
model_name='link',
name='id',
field=models.CharField(max_length=12, serialize=False, primary_key=True),
preserve_default=True,
),
]

View file

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('links', '0003_auto_20150117_2306'),
]
operations = [
migrations.RenameField(
model_name='link',
old_name='link',
new_name='url',
),
]

View file

54
links/models.py Normal file
View file

@ -0,0 +1,54 @@
from django.db import models
from django.forms import ModelForm, CharField, TextInput
import random
class Link(models.Model):
id = models.CharField(primary_key=True, max_length=12)
url = models.URLField(max_length=2048)
created_at = models.DateTimeField(auto_now_add=True)
clicks = models.IntegerField(default=0)
ip = models.GenericIPAddressField(null=True)
def __unicode__(self):
return self.url
def generate_unique_id(self, length=12):
attempts = 0
id = random_id()
try:
while Link.objects.get(id=id) and attempts < 10:
attempts = attempts + 1
id = random_id()
except:
pass
return id
def save(self, *args, **kwargs):
if not self.pk:
self.id = self.generate_unique_id()
super(Link, self).save(*args, **kwargs)
class LinkForm(ModelForm):
url = CharField(label='')
class Meta:
model = Link
fields = ['url']
def random_id():
rand = ''
for i in range(0,12):
rand += int_to_char(random.randint(0,61));
return rand;
def int_to_char(int):
if(int < 10):
char = chr(int + 48)
elif(int < 36):
char = chr(int + 55)
else:
char = chr(int + 61)
return char

View file

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="/static/style.css" />
<title>minie links!</title>
</head>
<body>
<div id="main-box">
<form method="post" action="/">
<ul>
{{form.as_ul}}
<li><input type="submit" value="shrink" name="shrink" id="main-submit" /></li>
</ul>
</form>
</div>
<div id="logo-wrap">
<div id="logo">
<a href="/"><img src="/static/minie.png" alt="min.ie" /></a>
</div>
{% if short_url %}
<form name="url">
<label onclick=\"document.url.short_link.focus();document.url.short_link.select();\" for=\"short_link\">Your Link</label>
<input name='short_link' value='{{short_url}}' id='short_link' readonly='true' size='25' onclick='javascript:this.focus();this.select();' />
</form>
{% endif %}
<div id="info">Drag this bookmarklet <a onclick="return false" href="javascript:void(window.location%20=%20'http://min.ie/'+window.location)">min.ie</a> to your bookmark bar, or just stick "min.ie/" before any link you want to shrink.</div>
<p>Django and Postgres Powered</p>
</div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-66209-5";
urchinTracker();
</script>
</body>
</html>

3
links/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

26
links/views.py Normal file
View file

@ -0,0 +1,26 @@
from django.shortcuts import render, redirect
from django.http import Http404
from .models import Link, LinkForm
from urlparse import urlparse
def catchall(request, id):
try:
link = Link.objects.get(id=id)
return redirect(link.url)
except:
parsed = urlparse(id)
if parsed.netloc:
link = Link(url=id)
link.save();
context = {'form': LinkForm}
context['short_url'] = "http://" + str(request.get_host()) + "/" + str(link.id)
return render(request, 'index.html', context)
raise Http404("Link does not exist")
def home(request):
context = {'form': LinkForm}
if 'link' in request.POST:
link = Link(link=request.POST['url'])
link.save();
context['short_url'] = "http://" + str(request.get_host()) + "/" + str(link.id)
return render(request, 'index.html', context)

View file

@ -17,7 +17,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DEBUG = True DEBUG = True
TEMPLATE_DEBUG = True TEMPLATE_DEBUG = True
SECRET_KEY = 'uz+*54ipcwwpjjwkt+hb4o_7y0o-%6=@+$rmm2yoaw_7j_=vjw' SECRET_KEY = os.environ['SECRET_KEY']
ALLOWED_HOSTS = ['*'] ALLOWED_HOSTS = ['*']
@ -30,16 +30,17 @@ INSTALLED_APPS = (
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'links',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', )
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'links/templates'),
) )
ROOT_URLCONF = 'minie.urls' ROOT_URLCONF = 'minie.urls'

View file

@ -5,6 +5,7 @@ urlpatterns = patterns('',
# Examples: # Examples:
# url(r'^$', 'minie.views.home', name='home'), # url(r'^$', 'minie.views.home', name='home'),
# url(r'^blog/', include('blog.urls')), # url(r'^blog/', include('blog.urls')),
url(r'^$', 'links.views.home', name='home'),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'(.*)', 'links.views.catchall', name='short'),
) )

BIN
static/minie.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

229
static/style.css Normal file
View file

@ -0,0 +1,229 @@
/***** Global Settings *****/
html, body {
border:0;
margin:0;
padding:0;
}
body {
font:100%/1.25 arial, helvetica, sans-serif;
}
/***** Common Formatting *****/
h1, h2, h3, h4, h5, h6 {
margin:0;
padding:0;
font-weight:normal;
}
h1 {
padding:30px 0 25px 0;
letter-spacing:-1px;
font:2em arial, helvetica, sans-serif;
}
h2 {
padding:20px 0;
letter-spacing:-1px;
font:1.5em arial, helvetica, sans-serif;
}
h3 {
font:1em arial, helvetica, sans-serif;
font-weight:bold;
}
p, ul, ol {
margin:0;
padding:0 0 15px 0;
}
ul, ol {
list-style: disc;
padding:0 0 15px 25px;
}
blockquote {
margin:22px 40px;
padding:0;
}
small {
font-size:0.85em;
}
img {
border:0;
}
sup {
position:relative;
bottom:0.3em;
vertical-align:baseline;
}
sub {
position:relative;
bottom:-0.2em;
vertical-align:baseline;
}
acronym, abbr {
cursor:help;
letter-spacing:1px;
border-bottom:1px dashed;
}
/***** Links *****/
a, a:visited {
text-decoration:none;
}
/***** Forms *****/
form {
margin:0;
padding:0;
display:inline;
}
input, select, textarea {
font:1em arial, helvetica, sans-serif;
}
textarea {
line-height:1.25;
}
label {
cursor:pointer;
}
/***** Tables *****/
table {
border:0;
margin:0 0 18px 0;
padding:0;
}
table tr td {
padding:2px;
}
/***** Wrapper *****/
#wrap {
width:660px;
margin:0 auto;
}
/***** Global Classes *****/
.clear { clear:both; }
.float-left { float:left; }
.float-right { float:right; }
.text-left { text-align:left; }
.text-right { text-align:right; }
.text-center { text-align:center; }
.text-justify { text-align:justify; }
.bold { font-weight:bold; }
.italic { font-style:italic; }
.underline { border-bottom:1px solid; }
.highlight { background:#ffc; }
.wrap { width:960px;margin:0 auto; }
.img-left { float:left;margin:4px 10px 4px 0; }
.img-right { float:right;margin:4px 0 4px 10px; }
.nopadding { padding:0; }
.noindent { margin-left:0;padding-left:0; }
.nobullet { list-style:none;list-style-image:none; }
body{
color: #666;
font-size: 16px;
}
input {
line-height: 24px;
}
#main-submit{
background: #ff3139;
color: #FFF;
line-height: 22px;
border-bottom: #b92329 solid 1px;
border-right: #b92329 solid 1px;
border-top: #ff3139 solid 1px;
border-left: #ff3139 solid 1px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
font-size: 1.2em;
}
#main-submit:active{
border-bottom: #ff3139 solid 1px;
border-right: #ff3139 solid 1px;
border-top: #b92329 solid 1px;
border-left: #b92329 solid 1px;
}
#main-box{
background: #4e9bd1;
width: 570px;color: #FFF;
padding-top: 20px;
padding-bottom: 20px;
border-bottom: #3d79a3 solid 1px;
border-right: #3d79a3 solid 1px;
border-top: #4e9bd1 solid 1px;
border-left: #4e9bd1 solid 1px;
margin: 0 auto;
margin-top: 20px;
text-align: center;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
#logo-wrap{
width: 570px;
margin: 0 auto;
margin-top: 20px;
margin-bottom: 20px;
}
#logo-wrap p{
text-align: right;
font-size: 10px;
color: #ddd;
}
#logo{
float:right;
}
#info{
padding-top:15px;
clear:both;
line-height: 24px;
}
#info a{
color: #4e9bd1;
padding: 4px 8px;
background: #EEE;
border-bottom: #CCC solid 1px;
border-right: #CCC solid 1px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
form ul {
padding: 0;
}
form li {
display: inline;
}
#id_url {
width: 400px;
}