commit 4b29603d79cc1f79c66786684f27ec9abfbaa825
Author: Tom Willemsen
Date: Mon Oct 17 01:34:04 2011 +0200
Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..db82c7d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.pyc
+local_settings.py
+static
+.toudou
+test.db
diff --git a/__init__.py b/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/blog/__init__.py b/blog/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/blog/admin.py b/blog/admin.py
new file mode 100644
index 0000000..ca32d1f
--- /dev/null
+++ b/blog/admin.py
@@ -0,0 +1,4 @@
+from blog.models import Post
+from django.contrib import admin
+
+admin.site.register(Post)
diff --git a/blog/models.py b/blog/models.py
new file mode 100644
index 0000000..126ba57
--- /dev/null
+++ b/blog/models.py
@@ -0,0 +1,33 @@
+from django.db import models
+from main.models import Tag, Activity
+from django.db.models.signals import post_save, post_delete
+
+class Post(models.Model):
+ subject = models.CharField(max_length=500)
+ body = models.TextField()
+ tags = models.ManyToManyField(Tag, null=True, blank=True)
+ postdate = models.DateTimeField(auto_now=True)
+
+ def __unicode__(self):
+ return self.subject
+
+def post_saved_callback(sender, **kwargs):
+ if kwargs['created']:
+ acttype = 'add'
+ else:
+ acttype = 'edit'
+
+ a = Activity(actcategory='blog',
+ actdescription=kwargs["instance"].subject,
+ acttype = acttype,
+ objpk = kwargs["instance"].pk)
+ a.save()
+
+def post_deleted_callback(sender, **kwargs):
+ a = Activity(actcategory='blog',
+ actdescription=kwargs["instance"].subject,
+ acttype = 'delete')
+ a.save()
+
+post_save.connect(post_saved_callback, sender=Post)
+post_delete.connect(post_deleted_callback, sender=Post)
diff --git a/blog/tests.py b/blog/tests.py
new file mode 100644
index 0000000..2247054
--- /dev/null
+++ b/blog/tests.py
@@ -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
+"""}
+
diff --git a/blog/urls.py b/blog/urls.py
new file mode 100644
index 0000000..c4137ed
--- /dev/null
+++ b/blog/urls.py
@@ -0,0 +1,9 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('blog.views',
+ (r'^$', 'index'),
+ (r'^(?P\d+)/$', 'index'),
+ (r'^post/(?P\d+)/$', 'post'),
+ (r'^tags/$', 'tags'),
+ (r'^tag/(?P[\w_]+)/$', 'tag'),
+)
diff --git a/blog/views.py b/blog/views.py
new file mode 100644
index 0000000..06a4aba
--- /dev/null
+++ b/blog/views.py
@@ -0,0 +1,55 @@
+# Create your views here.
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.template import Context, loader
+from django.views.generic.simple import direct_to_template
+from blog.models import Post, Tag
+
+def index(request, page=0):
+ item_count = 7
+
+ page = int(page)
+ start_num = (page * item_count)
+ end_num = start_num + item_count
+
+ post_list = Post.objects.all().order_by("-postdate")[start_num:end_num]
+
+ has_previous = page > 0
+ has_next = end_num < Post.objects.all().count()
+
+ c = {
+ 'postlist': post_list,
+ 'has_next': has_next,
+ 'has_previous': has_previous,
+ 'next_page': page + 1,
+ 'previous_page': page - 1
+ }
+
+ return direct_to_template(request, "blog/posts.html", c)
+
+def post(request, post_id):
+ post = Post.objects.filter(pk=post_id)
+ t = loader.get_template("blog/posts.html")
+ c = Context({
+ 'postlist': post,
+ })
+
+ return HttpResponse(t.render(c))
+
+def tags(request):
+ tag_list = Tag.objects.all()
+ t = loader.get_template("blog/tags.html")
+ c = Context({
+ 'taglist': tag_list,
+ })
+
+ return HttpResponse(t.render(c))
+
+def tag(request, tag_name):
+ post_list = Post.objects.filter(tags__name=tag_name)
+ t = loader.get_template("blog/posts.html")
+ c = Context({
+ 'postlist': post_list,
+ })
+
+ return HttpResponse(t.render(c))
diff --git a/links/__init__.py b/links/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/links/admin.py b/links/admin.py
new file mode 100644
index 0000000..29b8674
--- /dev/null
+++ b/links/admin.py
@@ -0,0 +1,4 @@
+from links.models import Bookmark
+from django.contrib import admin
+
+admin.site.register(Bookmark)
diff --git a/links/models.py b/links/models.py
new file mode 100644
index 0000000..50319a2
--- /dev/null
+++ b/links/models.py
@@ -0,0 +1,35 @@
+from django.db import models
+from main.models import Tag, Activity
+from django.db.models.signals import post_save, post_delete
+
+class Bookmark(models.Model):
+ url = models.URLField(primary_key=True, max_length=255)
+ date = models.DateTimeField(auto_now_add=True)
+ name = models.CharField(max_length=255)
+ description = models.TextField()
+# tags = models.ManyToManyField(Tag, null=True, blank=True)
+ priority = models.IntegerField(null=True, blank=True)
+
+ def __unicode__(self):
+ return self.name
+
+def bookmark_saved_callback(sender, **kwargs):
+ if kwargs['created']:
+ acttype = 'add'
+ else:
+ acttype = 'edit'
+
+ a = Activity(actcategory='link',
+ actdescription=kwargs["instance"].name,
+ acttype = acttype,
+ objpk = kwargs["instance"].pk)
+ a.save()
+
+def bookmark_deleted_callback(sender, **kwargs):
+ a = Activity(actcategory='link',
+ actdescription=kwargs["instance"].name,
+ acttype = 'delete')
+ a.save()
+
+post_save.connect(bookmark_saved_callback, sender=Bookmark)
+post_delete.connect(bookmark_deleted_callback, sender=Bookmark)
diff --git a/links/tests.py b/links/tests.py
new file mode 100644
index 0000000..501deb7
--- /dev/null
+++ b/links/tests.py
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this 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.assertEqual(1 + 1, 2)
diff --git a/links/urls.py b/links/urls.py
new file mode 100644
index 0000000..25d8cc8
--- /dev/null
+++ b/links/urls.py
@@ -0,0 +1,5 @@
+from django.conf.urls.defaults import patterns
+
+urlpatterns = patterns('links.views',
+ (r'^$', 'index'),
+)
diff --git a/links/views.py b/links/views.py
new file mode 100644
index 0000000..fe0d89d
--- /dev/null
+++ b/links/views.py
@@ -0,0 +1,12 @@
+from links.models import Bookmark
+from django.http import HttpResponse
+from django.template import Context, loader
+
+def index(request):
+ bookmark_list = Bookmark.objects.all().order_by("-date")[:100]
+ t = loader.get_template("links/links.html")
+ c = Context({
+ 'bookmarklist': bookmark_list,
+ })
+
+ return HttpResponse(t.render(c))
diff --git a/local_settings.py.example b/local_settings.py.example
new file mode 100644
index 0000000..6a166a7
--- /dev/null
+++ b/local_settings.py.example
@@ -0,0 +1,15 @@
+DEBUG = False
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': '', # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = '00000000000000000000000000000000000000000000000000'
diff --git a/main/__init__.py b/main/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/main/admin.py b/main/admin.py
new file mode 100644
index 0000000..093f769
--- /dev/null
+++ b/main/admin.py
@@ -0,0 +1,4 @@
+from main.models import Tag
+from django.contrib import admin
+
+admin.site.register(Tag)
diff --git a/main/models.py b/main/models.py
new file mode 100644
index 0000000..8ecddec
--- /dev/null
+++ b/main/models.py
@@ -0,0 +1,24 @@
+from django.db import models
+
+class Tag(models.Model):
+ name = models.CharField(primary_key=True, max_length=200)
+
+ def __unicode__(self):
+ return self.name
+
+class Activity(models.Model):
+ ACTCATEGORY_CHOICES = (
+ ('blog', 'Blog post'),
+ ('project', 'Project page'),
+ ('link', 'Link'),
+ )
+ ACTTYPE_CHOICES = (
+ ('add', 'Add'),
+ ('edit', 'Edit'),
+ ('delete', 'Delete'),
+ )
+ date = models.DateTimeField(auto_now=True)
+ actcategory = models.CharField(max_length=100, choices=ACTCATEGORY_CHOICES)
+ actdescription = models.CharField(max_length=500)
+ acttype = models.CharField(max_length=6)
+ objpk = models.CharField(max_length=300, null=True)
diff --git a/main/signals.py b/main/signals.py
new file mode 100644
index 0000000..e69de29
diff --git a/main/tests.py b/main/tests.py
new file mode 100644
index 0000000..2247054
--- /dev/null
+++ b/main/tests.py
@@ -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
+"""}
+
diff --git a/main/urls.py b/main/urls.py
new file mode 100644
index 0000000..9f861b5
--- /dev/null
+++ b/main/urls.py
@@ -0,0 +1,4 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('main.views',
+ (r'^$', 'index'))
diff --git a/main/views.py b/main/views.py
new file mode 100644
index 0000000..91e20dd
--- /dev/null
+++ b/main/views.py
@@ -0,0 +1,13 @@
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.template import Context, loader
+from main.models import Activity
+
+def index(request):
+ activity_list = Activity.objects.all().order_by("-date")[:5]
+ t = loader.get_template("home.html")
+ c = Context({
+ "activitylist": activity_list,
+ })
+
+ return HttpResponse(t.render(c))
diff --git a/manage.py b/manage.py
new file mode 100644
index 0000000..6a43c99
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python2
+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)
diff --git a/projects/__init__.py b/projects/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/projects/admin.py b/projects/admin.py
new file mode 100644
index 0000000..b5ec7d4
--- /dev/null
+++ b/projects/admin.py
@@ -0,0 +1,6 @@
+from projects.models import Project, Language, Screenshot
+from django.contrib import admin
+
+admin.site.register(Project)
+admin.site.register(Language)
+admin.site.register(Screenshot)
diff --git a/projects/models.py b/projects/models.py
new file mode 100644
index 0000000..4b2b49a
--- /dev/null
+++ b/projects/models.py
@@ -0,0 +1,59 @@
+from django.db import models
+from main.models import Tag, Activity
+from django.db.models.signals import post_save, post_delete
+
+class Language(models.Model):
+ name = models.CharField(max_length=100)
+
+ def __unicode__(self):
+ return self.name
+
+class Screenshot(models.Model):
+ url = models.URLField(max_length=255)
+ description = models.CharField(max_length=300)
+
+ def __unicode__(self):
+ return self.description
+
+class Project(models.Model):
+ STATUS_CHOICES = (
+ ('active', "Active"),
+ ('onhold', "On Hold"),
+ ('dropped', "Dropped"),
+ )
+
+ slug = models.SlugField(max_length=255, primary_key=True)
+ name = models.CharField(max_length=300)
+ status = models.CharField(max_length=8, choices=STATUS_CHOICES)
+ tagline = models.CharField(max_length=140, null=True, blank=True)
+ languages = models.ManyToManyField(Language, null=True, blank=True)
+ source_url = models.URLField(max_length=255, null=True, blank=True)
+ bugtracker_url = models.URLField(max_length=255, null=True, blank=True)
+ wiki_url = models.URLField(max_length=255, null=True, blank=True)
+ description = models.TextField()
+ screenshots = models.ForeignKey(Screenshot, null=True, blank=True)
+# tags = models.ManyToManyField(Tag, null=True, blank=True)
+
+ def __unicode__(self):
+ return self.name
+
+def project_saved_callback(sender, **kwargs):
+ if kwargs['created']:
+ acttype = 'add'
+ else:
+ acttype = 'edit'
+
+ a = Activity(actcategory='project',
+ actdescription=kwargs["instance"].name,
+ acttype = acttype,
+ objpk = kwargs["instance"].pk)
+ a.save()
+
+def project_deleted_callback(sender, **kwargs):
+ a = Activity(actcategory='project',
+ actdescription=kwargs["instance"].name,
+ acttype = 'delete')
+ a.save()
+
+post_save.connect(project_saved_callback, sender=Project)
+post_delete.connect(project_deleted_callback, sender=Project)
diff --git a/projects/urls.py b/projects/urls.py
new file mode 100644
index 0000000..053ab5b
--- /dev/null
+++ b/projects/urls.py
@@ -0,0 +1,13 @@
+from django.conf.urls.defaults import *
+from projects.models import Project, Language
+
+project_info_dict = {
+ 'queryset': Project.objects.all(),
+}
+
+urlpatterns = patterns('',
+ (r'^$',
+ 'django.views.generic.list_detail.object_list',
+ project_info_dict),
+ (r'^(?P[\w-]+)/$', 'projects.views.project'),
+)
diff --git a/projects/views.py b/projects/views.py
new file mode 100644
index 0000000..ad46ebd
--- /dev/null
+++ b/projects/views.py
@@ -0,0 +1,24 @@
+from django.http import HttpResponse
+from django.template import Context, loader
+from projects.models import Project
+
+def project(request, object_id):
+ project = Project.objects.get(pk=object_id)
+ stats_dict = {
+ "Status": project.get_status_display(),
+ "Languages": ", ".join([language.name for language in project.languages.all()]),
+ }
+ links_dict = {
+ "Source": project.source_url,
+ "Bugtracker": project.bugtracker_url,
+ "Wiki": project.wiki_url,
+ }
+
+ t = loader.get_template("projects/project_detail.html")
+ c = Context({
+ "object": project,
+ "stats": stats_dict,
+ "links": links_dict,
+ })
+
+ return HttpResponse(t.render(c))
diff --git a/settings.py b/settings.py
new file mode 100644
index 0000000..2ef7e8f
--- /dev/null
+++ b/settings.py
@@ -0,0 +1,91 @@
+# Django settings for website project.
+import os, sys
+from local_settings import *
+
+DEPLOY_PATH = os.path.dirname(os.path.abspath(__file__))
+sys.path.insert(0, DEPLOY_PATH)
+
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ ('Tom Willemsen', 'ryuslash@gmail.com'),
+)
+
+MANAGERS = ADMINS
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'Europe/Brussels'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+USE_L10N = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+ROOT_URLCONF = 'urls'
+
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ '%s/templates' % DEPLOY_PATH,
+)
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.messages',
+ # Uncomment the next line to enable the admin:
+ 'django.contrib.admin',
+ # Uncomment the next line to enable admin documentation:
+ # 'django.contrib.admindocs',
+ 'main',
+ 'blog',
+ 'projects',
+ 'links',
+)
diff --git a/templates/admin/login.html b/templates/admin/login.html
new file mode 100644
index 0000000..eba271f
--- /dev/null
+++ b/templates/admin/login.html
@@ -0,0 +1,50 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block extrastyle %}{% load adminmedia %}{{ block.super }}{% endblock %}
+
+{% block bodyclass %}login{% endblock %}
+
+{% block nav-global %}{% endblock %}
+
+{% block content_title %}{% endblock %}
+
+{% block breadcrumbs %}{% endblock %}
+
+{% block content %}
+{% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %}
+
+{% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
+
+{% endif %}
+
+{% if form.non_field_errors or form.this_is_the_login_form.errors %}
+{% for error in form.non_field_errors|add:form.this_is_the_login_form.errors %}
+