Sort of works now
This commit is contained in:
parent
593f3e6d1c
commit
5972323cc1
15 changed files with 453 additions and 6 deletions
0
links/__init__.py
Normal file
0
links/__init__.py
Normal file
3
links/admin.py
Normal file
3
links/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
27
links/migrations/0001_initial.py
Normal file
27
links/migrations/0001_initial.py
Normal 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,),
|
||||
),
|
||||
]
|
20
links/migrations/0002_auto_20150117_2248.py
Normal file
20
links/migrations/0002_auto_20150117_2248.py
Normal 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,
|
||||
),
|
||||
]
|
24
links/migrations/0003_auto_20150117_2306.py
Normal file
24
links/migrations/0003_auto_20150117_2306.py
Normal 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,
|
||||
),
|
||||
]
|
19
links/migrations/0004_auto_20150117_2338.py
Normal file
19
links/migrations/0004_auto_20150117_2338.py
Normal 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',
|
||||
),
|
||||
]
|
0
links/migrations/__init__.py
Normal file
0
links/migrations/__init__.py
Normal file
54
links/models.py
Normal file
54
links/models.py
Normal 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
|
40
links/templates/index.html
Normal file
40
links/templates/index.html
Normal 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
3
links/tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
26
links/views.py
Normal file
26
links/views.py
Normal 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)
|
|
@ -17,7 +17,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
|||
DEBUG = True
|
||||
TEMPLATE_DEBUG = True
|
||||
|
||||
SECRET_KEY = 'uz+*54ipcwwpjjwkt+hb4o_7y0o-%6=@+$rmm2yoaw_7j_=vjw'
|
||||
SECRET_KEY = os.environ['SECRET_KEY']
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
|
@ -30,16 +30,17 @@ INSTALLED_APPS = (
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'links',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
)
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
os.path.join(BASE_DIR, 'links/templates'),
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'minie.urls'
|
||||
|
|
|
@ -5,6 +5,7 @@ urlpatterns = patterns('',
|
|||
# Examples:
|
||||
# url(r'^$', 'minie.views.home', name='home'),
|
||||
# url(r'^blog/', include('blog.urls')),
|
||||
|
||||
url(r'^$', 'links.views.home', name='home'),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'(.*)', 'links.views.catchall', name='short'),
|
||||
)
|
||||
|
|
BIN
static/minie.png
Normal file
BIN
static/minie.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
229
static/style.css
Normal file
229
static/style.css
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue