Permalink
Browse files

Initial commit - Django image hosting/sharing.

Similar to imgur, imageshack, etc. Simply upload
images to your private little chunk of webspace.

TODO: Add LICENSE (MIT/BSD)

Note: Several glaring bugs exist. Releasing early rather than later.
Been sitting on this for some time and just want it "out there".
  • Loading branch information...
Ryan S
Ryan S committed Jun 20, 2011
0 parents commit 046f82fd56c8ce4bf9add1776d3be5eafb367699
@@ -0,0 +1,10 @@
+settings.py
+data/thumbs/*
+data/*.jpg
+data/*.png
+data/*.gif
+db/*.sql
+*.wsgi
+log/*_log
+
+
No changes.
@@ -0,0 +1,36 @@
+/*
+ ColorBox Core Style
+ The following rules are the styles that are consistant between themes.
+ Avoid changing this area to maintain compatability with future versions of ColorBox.
+*/
+#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;}
+#cboxOverlay{position:fixed; width:100%; height:100%;}
+#cboxMiddleLeft, #cboxBottomLeft{clear:left;}
+#cboxContent{position:relative;}
+#cboxLoadedContent{overflow:auto;}
+#cboxLoadedContent iframe{display:block; width:100%; height:100%; border:0;}
+#cboxTitle{margin:0;}
+#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%;}
+#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
+
+/*
+ ColorBox example user style
+ The following rules are ordered and tabbed in a way that represents the
+ order/nesting of the generated HTML, so that the structure easier to understand.
+*/
+#cboxOverlay{background:#000;}
+
+#colorbox{}
+ #cboxContent{margin-top:20px;}
+ #cboxLoadedContent{background:#000; padding:5px;}
+ #cboxTitle{position:absolute; top:-20px; left:0; color:#ccc;}
+ #cboxCurrent{position:absolute; top:-20px; right:0px; color:#ccc;}
+ #cboxSlideshow{position:absolute; top:-20px; right:90px; color:#fff;}
+ #cboxPrevious{position:absolute; top:50%; left:5px; margin-top:-32px; background:url(images/controls.png) no-repeat top left; width:28px; height:65px; text-indent:-9999px;}
+ #cboxPrevious.hover{background-position:bottom left;}
+ #cboxNext{position:absolute; top:50%; right:5px; margin-top:-32px; background:url(images/controls.png) no-repeat top right; width:28px; height:65px; text-indent:-9999px;}
+ #cboxNext.hover{background-position:bottom right;}
+ #cboxLoadingOverlay{background:#000;}
+ #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;}
+ #cboxClose{position:absolute; top:5px; right:5px; display:block; background:url(images/controls.png) no-repeat top center; width:38px; height:19px; text-indent:-9999px;}
+ #cboxClose.hover{background-position:bottom center;}

Large diffs are not rendered by default.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,65 @@
+body {
+ background: #333;
+ color: #eee;
+ font-family: Verdana, sans-serif;
+ font-size: 10pt;
+}
+
+a {
+ color: #3cf;
+}
+
+a:hover {
+ color: red;
+}
+
+div.image {
+ display: inline-block;
+ border: 1px solid #999;
+ background: #666;
+ margin: 0.5em;
+ padding: 0.5em;
+
+ width: 200px;
+ font-size: 75%;
+ vertical-align: top;
+}
+
+div.image input {
+ border: 1px solid #999;
+ background: #333;
+ color: #eee;
+}
+
+div.image:hover {
+ background: #999;
+ border: 1px solid #ccc;
+}
+
+div.image a.imglink img {
+ display:block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+#wrapper {
+ /*width: 70%;*/
+ border-radius: 10px;
+ margin-left: auto;
+ margin-right: auto;
+ padding: 1em;
+ text-align: center;
+
+ background: #444;
+ border: 1px solid #666;
+
+}
+
+#footer {
+ text-align: center;
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+
+ font-size: 75%;
+}
No changes.
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# Port of my php base62 numbering thingy.
+
+def base62(num):
+ BASE62_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+ result = []
+ while( num > 61 ):
+ result.append( BASE62_CHARS[ (num % 62) ] )
+ num = num // 62
+
+ result.append( BASE62_CHARS[ (num % 62) ] )
+
+ result = "".join(result)
+ return result[::-1]
+
+if __name__=="__main__":
+ # test/easy use
+ import sys
+ print base62(int(sys.argv[1]))
@@ -0,0 +1,16 @@
+from django.db import models
+
+class Image(models.Model):
+ id = models.IntegerField(primary_key=True)
+ base62 = models.CharField(unique=True, max_length=48)
+ filename = models.CharField(max_length=36)
+ orig_filename = models.CharField(max_length=765, blank=True)
+ type = models.CharField(max_length=192, null=True, blank=True)
+ md5sum = models.CharField(unique=True, max_length=96, blank=True)
+ description = models.CharField(max_length=765, null=True, blank=True)
+ date_added = models.CharField(max_length=765)
+ uploader = models.ForeignKey('auth.User', blank=True, null=True)
+ class Meta:
+ db_table = u'images'
+
+
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
@@ -0,0 +1,101 @@
+import os
+import hashlib
+import urllib2
+
+from django.template import RequestContext
+from django.shortcuts import get_object_or_404, render_to_response
+from django.http import HttpResponseRedirect, HttpResponse
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
+# App specific imports
+from images.image.models import Image
+from images.image.base62 import base62
+from images import settings
+
+@login_required
+def upload(request):
+ if request.method == 'GET':
+ return render_to_response('upload.html', {'url': request.GET.get('url', ''),}, context_instance=RequestContext(request))
+ elif request.method == 'POST':
+ if request.POST['upload_type'] == 'file':
+ file = request.FILES['upload_file']
+ img = Image()
+ try:
+ next_id = Image.objects.order_by('-id')[0].id + 1
+ except IndexError:
+ next_id = settings.IMAGE_ID_OFFSET + 1
+
+ img.base62 = base62(next_id)
+ img.filename = base62(next_id) + "." + file.name[-3:]
+ img.orig_filename = file.name
+ img.type = file.content_type
+ img.description = '' # not implemented yet.
+ img.uploader = request.user
+
+ image_file = os.path.join(settings.MEDIA_ROOT,img.filename)
+ thumbnail = os.path.join(settings.MEDIA_ROOT, 'thumbs', img.filename)
+
+ md5 = hashlib.md5()
+ f = open(image_file, "wb+")
+ for chunk in file.chunks():
+ f.write(chunk)
+ md5.update(chunk)
+ f.close()
+ img.md5sum = md5.hexdigest()
+
+ os.system("/usr/bin/convert %s -thumbnail 150x150 %s" % (image_file, thumbnail))
+ img.save()
+
+ return HttpResponseRedirect('/i/' + img.base62)
+
+ elif request.POST['upload_type'] == 'url':
+ remote_image = urllib2.urlopen(request.POST['upload_url'])
+ md5 = hashlib.md5()
+
+ data = remote_image.read()
+ md5.update(data)
+
+ img = Image()
+ try:
+ next_id = Image.objects.order_by('-id')[0].id + 1
+ except IndexError:
+ next_id = settings.IMAGE_ID_OFFSET + 1
+
+ img.base62 = base62(next_id)
+ img.filename = base62(next_id) + "." + request.POST['upload_url'][-3:]
+ img.orig_filename = request.POST['upload_url']
+ img.type = ''
+ img.description = '' # not implemented yet.
+ img.uploader = request.user
+ img.md5sum = md5.hexdigest()
+
+ image_file = os.path.join(settings.MEDIA_ROOT,img.filename)
+ thumbnail = os.path.join(settings.MEDIA_ROOT, 'thumbs', img.filename)
+ f = open(image_file, "wb+")
+ f.write(data)
+ f.close()
+
+ img.save()
+ os.system("/usr/bin/convert %s -thumbnail 150x150 %s" % (image_file, thumbnail))
+
+ return HttpResponseRedirect('/i/' + img.base62)
+
+@login_required
+def view_image(request, id):
+ return render_to_response('view_image.html',
+ {'image': Image.objects.get(base62=id)}, context_instance=RequestContext(request))
+
+@login_required
+def list_images(request, page=0):
+ return render_to_response('list_images.html',
+ {'page':page, 'images': Image.objects.all()}, context_instance=RequestContext(request))
+
+@login_required
+def user_images(request, user=None):
+ if user == None:
+ user = request.user
+ else:
+ user = User.objects.get(username=user)
+
+ return render_to_response('list_images.html',
+ {'images': Image.objects.filter(uploader=user), }, context_instance=RequestContext(request))
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
Oops, something went wrong.

0 comments on commit 046f82f

Please sign in to comment.