Django site project. Apps installed:
* Article
This is a simple "article" application with ReST support. Instances could
be marked as "main" and a templatetag retrieve them.
* Blog
Django blog application, needs a better integration yet.
* Download
Little application to manage "download" links
* Link
Little application to manage links (like those displayed on top and in the
footer)
--HG--
extra : convert_revision : svn%3Ab85faa78-f9eb-468e-a121-7cced6da292c%403
|
|
@ -0,0 +1,4 @@
|
|||
Dependencies:
|
||||
|
||||
* python docutils (python-docutils in debian)
|
||||
Needed for ReST markup
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
REST_HELP_TEXT = _("""ReST markup language allowed
|
||||
<a href='http://en.wikipedia.org/wiki/ReStructuredText'>
|
||||
Read more</a>""")
|
||||
|
||||
MAIN_HELP_TEXT = _("Useful to filter articles, like those public on homepage")
|
||||
|
||||
|
||||
class Article(models.Model):
|
||||
title = models.CharField(_("title"), max_length=256, core=True,
|
||||
blank=False)
|
||||
slug = models.SlugField(_("slug"), prepopulate_from=("title",),
|
||||
editable=False)
|
||||
text = models.TextField(_("text"), core=True, help_text=REST_HELP_TEXT)
|
||||
main = models.BooleanField(_("main"), core=True, blank=False,
|
||||
default=False, help_text=MAIN_HELP_TEXT)
|
||||
order = models.IntegerField(_("order"), core=True, blank=False, default=0)
|
||||
|
||||
|
||||
# automatic dates
|
||||
created = models.DateTimeField(core=True, editable=False)
|
||||
updated = models.DateTimeField(core=True, editable=False)
|
||||
|
||||
|
||||
def order_up(self):
|
||||
self.order += 1
|
||||
self.save()
|
||||
|
||||
def order_down(self):
|
||||
self.order -= 1
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
if not self.id:
|
||||
self.created = datetime.now()
|
||||
self.updated = datetime.now()
|
||||
self.slug = slugify(self.title)
|
||||
super(Article, self).save()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
# ugly, but django-admin isn't very versatile right now
|
||||
def order_link(self):
|
||||
return _("%(order)s (<a href='/article/%(id)s/order/up/'>Up</a>" \
|
||||
" | <a href='/article/%(id)s/order/down/'>Down</a>)") % \
|
||||
{ "order": self.order, "id": self.id }
|
||||
order_link.short_description = u"order"
|
||||
order_link.allow_tags = True
|
||||
|
||||
class Admin:
|
||||
list_display = ("title", "main", "order_link", "updated")
|
||||
list_filter = ("main", "created")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("article")
|
||||
verbose_name_plural = _("articles")
|
||||
ordering = [ "-order", ]
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
from django import template
|
||||
|
||||
from lib.templatetags import *
|
||||
|
||||
from article.models import Article
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.tag(name="load_main_articles")
|
||||
def do_load_main_articles(parser, token):
|
||||
return do_load(parser, token, True)
|
||||
|
||||
|
||||
@register.tag(name="load_last_articles")
|
||||
def do_load_last_articles(parser, token):
|
||||
return do_load(parser, token)
|
||||
|
||||
|
||||
def do_load(parser, token, only_main=False):
|
||||
syntax_msg = 'Syntax: %s "COUNT" as "VAR_NAME"'
|
||||
|
||||
try:
|
||||
tag, count, _as, var_name = token.split_contents()
|
||||
|
||||
if not is_string(count) or not is_string(var_name):
|
||||
raise_syntax(syntax_msg % tag)
|
||||
count = int(unquoute(count))
|
||||
except:
|
||||
raise_syntax(syntax_msg % token.split_contents()[0])
|
||||
return LoadArticlesNode(count, unquoute(var_name), only_main)
|
||||
|
||||
|
||||
class LoadArticlesNode(template.Node):
|
||||
def __init__(self, count, var_name, only_main=False):
|
||||
self.only_main = only_main
|
||||
self.count = count
|
||||
self.var_name = var_name
|
||||
|
||||
def render(self, context):
|
||||
articles = Article.objects.all()
|
||||
if self.only_main:
|
||||
articles = articles.filter(main=True)
|
||||
|
||||
context[self.var_name] = articles[:self.count]
|
||||
return ''
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
from article.views import *
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r"^(?P<article_id>\d+)/order/up/$", order_up),
|
||||
(r"^(?P<article_id>\d+)/order/down/$", order_down),
|
||||
)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from django.shortcuts import get_object_or_404
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
from article.models import Article
|
||||
|
||||
|
||||
def order_up(request, article_id):
|
||||
article = get_object_or_404(Article, pk=article_id)
|
||||
article.order_up()
|
||||
return HttpResponseRedirect("/admin/article/article/")
|
||||
|
||||
|
||||
def order_down(request, article_id):
|
||||
article = get_object_or_404(Article, pk=article_id)
|
||||
article.order_down()
|
||||
return HttpResponseRedirect("/admin/article/article/")
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
from django.contrib.syndication.feeds import Feed
|
||||
from django_website.apps.blog.models import Entry
|
||||
import datetime
|
||||
|
||||
class WeblogEntryFeed(Feed):
|
||||
title = "The Django weblog"
|
||||
link = "http://www.djangoproject.com/weblog/"
|
||||
description = "Latest news about Django, the Python Web framework."
|
||||
|
||||
def items(self):
|
||||
return Entry.objects.filter(pub_date__lte=datetime.datetime.now())[:10]
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.pub_date
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import datetime
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Entry(models.Model):
|
||||
pub_date = models.DateTimeField()
|
||||
slug = models.SlugField(unique_for_date='pub_date')
|
||||
headline = models.CharField(max_length=200)
|
||||
summary = models.TextField(help_text="Use raw HTML.")
|
||||
body = models.TextField(help_text="Use raw HTML.")
|
||||
author = models.CharField(max_length=100)
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = 'entries'
|
||||
ordering = ('-pub_date',)
|
||||
get_latest_by = 'pub_date'
|
||||
|
||||
class Admin:
|
||||
list_display = ('pub_date', 'headline', 'author')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.headline
|
||||
|
||||
def get_absolute_url(self):
|
||||
return "/weblog/%s/%s/" % (self.pub_date.strftime("%Y/%b/%d").lower(), self.slug)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
from django import template
|
||||
from django_website.apps.blog.models import Entry
|
||||
import datetime
|
||||
|
||||
class LatestBlogEntriesNode(template.Node):
|
||||
def __init__(self, num, varname):
|
||||
self.num, self.varname = num, varname
|
||||
|
||||
def render(self, context):
|
||||
context[self.varname] = list(Entry.objects.filter(pub_date__lte=datetime.datetime.now())[:self.num])
|
||||
return ''
|
||||
|
||||
def do_get_latest_blog_entries(parser, token):
|
||||
"""
|
||||
{% get_latest_blog_entries 2 as latest_entries %}
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) != 4:
|
||||
raise template.TemplateSyntaxError, "'%s' tag takes three arguments" % bits[0]
|
||||
if bits[2] != 'as':
|
||||
raise template.TemplateSyntaxError, "First argument to '%s' tag must be 'as'" % bits[0]
|
||||
return LatestBlogEntriesNode(bits[1], bits[3])
|
||||
|
||||
register = template.Library()
|
||||
register.tag('get_latest_blog_entries', do_get_latest_blog_entries)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from django.conf.urls.defaults import *
|
||||
from models import Entry # relative import
|
||||
|
||||
info_dict = {
|
||||
'queryset': Entry.objects.all(),
|
||||
'date_field': 'pub_date',
|
||||
}
|
||||
|
||||
urlpatterns = patterns('django.views.generic.date_based',
|
||||
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[\w-]+)/$', 'object_detail', dict(info_dict, slug_field='slug')),
|
||||
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'archive_day', info_dict),
|
||||
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict),
|
||||
(r'^(?P<year>\d{4})/$', 'archive_year', info_dict),
|
||||
(r'^/?$', 'archive_index', info_dict),
|
||||
)
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class DownloadLink(models.Model):
|
||||
description = models.CharField(_("description"), max_length=512,
|
||||
blank=True, default='')
|
||||
address = models.CharField(_("address"), max_length=1024, blank=False)
|
||||
text = models.CharField(_("link text"), max_length=512, blank=False,
|
||||
default=_("download"))
|
||||
public = models.BooleanField(_("public"), core=True, blank=False,
|
||||
default=True)
|
||||
|
||||
# automatic dates
|
||||
created = models.DateTimeField(_("created"), core=True, editable=False)
|
||||
updated = models.DateTimeField(_("updated"), core=True, editable=False)
|
||||
|
||||
def toggle_public(self):
|
||||
self.public = not self.public
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
if not self.id:
|
||||
self.created = datetime.now()
|
||||
self.updated = datetime.now()
|
||||
super(DownloadLink, self).save()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.address
|
||||
|
||||
# ugly, but django-admin isn't very versatile right now
|
||||
def public_link(self):
|
||||
return _("%(status)s (<a href='/download/%(id)s/public/toggle/'>toggle</a>)") % \
|
||||
{ 'status': self.public and _("Yes") or _("No"),
|
||||
'id': self.id }
|
||||
public_link.short_description = u"public"
|
||||
public_link.allow_tags = True
|
||||
|
||||
class Admin:
|
||||
list_display = ("text", "address", "public_link", "created")
|
||||
list_filter = ("public", "created")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("download link")
|
||||
verbose_name_plural = _("download links")
|
||||
ordering = ["-created",]
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
from django import template
|
||||
|
||||
from lib.templatetags import *
|
||||
|
||||
from download.models import DownloadLink
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.tag(name="load_download_links")
|
||||
def do_load_links(parser, token):
|
||||
syntax_msg = 'Syntax: %s "COUNT" as "VAR_NAME"'
|
||||
|
||||
try:
|
||||
splited = token.split_contents()
|
||||
if len(splited) == 4:
|
||||
tag, count, _as, var_name = splited
|
||||
elif len(splited) == 3:
|
||||
tag, _as, var_name = splited
|
||||
count = None
|
||||
|
||||
if count and not is_string(count) or not is_string(var_name):
|
||||
raise_syntax(syntax_msg % tag)
|
||||
count = count and int(unquoute(count)) or count
|
||||
except:
|
||||
raise_syntax(syntax_msg % token.split_contents()[0])
|
||||
return LoadLinksNode(count, unquoute(var_name))
|
||||
|
||||
|
||||
class LoadLinksNode(template.Node):
|
||||
def __init__(self, count, var_name):
|
||||
self.count = count
|
||||
self.var_name = var_name
|
||||
|
||||
def render(self, context):
|
||||
links = DownloadLink.objects.filter(public=True)[:self.count]
|
||||
context[self.var_name] = links
|
||||
return ''
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
from download.views import *
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r"^(?P<link_id>\d+)/public/toggle/$", toggle_public),
|
||||
)
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
from django.shortcuts import get_object_or_404
|
||||
from django.http import HttpResponseRedirect
|
||||
|
||||
from download.models import DownloadLink
|
||||
|
||||
|
||||
def toggle_public(request, link_id):
|
||||
link = get_object_or_404(DownloadLink, pk=link_id)
|
||||
link.toggle_public()
|
||||
return HttpResponseRedirect("/admin/download/downloadlink/")
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class Group(models.Model):
|
||||
name = models.CharField(_("name"), max_length=64, core=True, blank=False)
|
||||
slug = models.SlugField(_("slug"), editable=False, unique=True,
|
||||
prepopulate_from=("name",))
|
||||
|
||||
# automatic dates
|
||||
created = models.DateTimeField(_("created"), core=True, editable=False)
|
||||
updated = models.DateTimeField(_("updated"), core=True, editable=False)
|
||||
|
||||
def save(self):
|
||||
if not self.id:
|
||||
self.created = datetime.now()
|
||||
self.updated = datetime.now()
|
||||
self.slug = slugify(self.name)
|
||||
super(Group, self).save()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("group")
|
||||
verbose_name_plural = _("groups")
|
||||
|
||||
class Admin:
|
||||
list_display = ("name", "slug",)
|
||||
|
||||
|
||||
class Link(models.Model):
|
||||
text = models.CharField(_("text"), max_length=1024, core=True, blank=False)
|
||||
address = models.CharField(_("address"), max_length=1024, core=True,
|
||||
blank=False)
|
||||
group = models.ManyToManyField(Group, verbose_name=_("group"), blank=True,
|
||||
null=False)
|
||||
|
||||
# automatic dates
|
||||
created = models.DateTimeField(core=True, editable=False)
|
||||
updated = models.DateTimeField(core=True, editable=False)
|
||||
|
||||
def save(self):
|
||||
if not self.id:
|
||||
self.created = datetime.now()
|
||||
self.updated = datetime.now()
|
||||
super(Link, self).save()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.address
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("link")
|
||||
verbose_name_plural = _("links")
|
||||
|
||||
class Admin:
|
||||
list_display = ("text", "address",)
|
||||
list_filter = ("group", )
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
from django import template
|
||||
|
||||
from lib.templatetags import *
|
||||
|
||||
from link.models import Group
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.tag(name="load_links")
|
||||
def do_load_links(parser, token):
|
||||
syntax_msg = 'Template tag syntax: load_links "SLUG_NAME" as "VAR_NAME"'
|
||||
|
||||
try:
|
||||
tag, slug, _as, var_name = token.split_contents()
|
||||
if not is_string(slug) or not is_string(var_name):
|
||||
raise_syntax(syntax_msg)
|
||||
except:
|
||||
raise_syntax(syntax_msg)
|
||||
return LoadLinksNode(unquoute(slug), unquoute(var_name))
|
||||
|
||||
|
||||
class LoadLinksNode(template.Node):
|
||||
def __init__(self, slug, var_name):
|
||||
self.slug = slug
|
||||
self.var_name = var_name
|
||||
|
||||
def render(self, context):
|
||||
group = Group.objects.get(slug=self.slug)
|
||||
context[self.var_name] = group and group.link_set.all() or []
|
||||
return ''
|
||||
|
|
@ -0,0 +1 @@
|
|||
# Create your views here.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from django import template
|
||||
|
||||
|
||||
is_string = lambda val: val[0] in ("'", '"') and val[0] == val[-1]
|
||||
unquoute = lambda val: val[1:-1]
|
||||
|
||||
def raise_syntax(msg):
|
||||
raise template.TemplateSyntaxError, msg
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import os
|
||||
|
||||
|
||||
DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||
DATABASE_NAME = '' # Or path to database file if using sqlite3.
|
||||
DATABASE_USER = '' # Not used with sqlite3.
|
||||
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
||||
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
||||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||
|
||||
SITE_URL = ''
|
||||
|
||||
SITE_MEDIA = os.path.join(os.path.dirname(__file__), 'static')
|
||||
|
||||
EMAIL_HOST = ''
|
||||
EMAIL_HOST_USER = ''
|
||||
EMAIL_HOST_PASSWORD = ''
|
||||
|
||||
MOBILE = False
|
||||
|
||||
PRODUCTION = False
|
||||
|
|
@ -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)
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Django settings for scrapy project.
|
||||
|
||||
from os.path import abspath, dirname, basename, join
|
||||
import sys
|
||||
|
||||
PROJECT_ABSOLUTE_DIR = dirname(abspath(__file__))
|
||||
PROJECT_NAME = basename(PROJECT_ABSOLUTE_DIR)
|
||||
|
||||
ADMINS = (
|
||||
# ('Your Name', 'your_email@domain.com'),
|
||||
)
|
||||
|
||||
MANAGERS = ADMINS
|
||||
|
||||
DEFAULT_CHARSET = "utf-8"
|
||||
|
||||
# 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 avilable on all operating systems.
|
||||
# If running in a Windows environment this must be set to the same as your
|
||||
# system time zone.
|
||||
TIME_ZONE = 'America/Montevideo'
|
||||
|
||||
# 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
|
||||
|
||||
# Absolute path to the directory that holds media.
|
||||
# Example: "/home/media/media.lawrence.com/"
|
||||
MEDIA_ROOT = join(PROJECT_ABSOLUTE_DIR, "static")
|
||||
|
||||
# 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 = '/site-media'
|
||||
|
||||
# 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/'
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = 'fq04ss$#1h=m=39sh4vvph+76i5u716z1-x5$$9xn7sb6y4-di'
|
||||
|
||||
# List of callables that know how to import templates from various sources.
|
||||
TEMPLATE_LOADERS = (
|
||||
'django.template.loaders.filesystem.load_template_source',
|
||||
'django.template.loaders.app_directories.load_template_source',
|
||||
# 'django.template.loaders.eggs.load_template_source',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.middleware.doc.XViewMiddleware',
|
||||
#'%s.middleware.threadlocals.ThreadLocals' % PROJECT_NAME,
|
||||
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = '%s.urls' % PROJECT_NAME
|
||||
|
||||
TEMPLATE_DIRS = (
|
||||
join(PROJECT_ABSOLUTE_DIR, "templates"),
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.markup',
|
||||
'django.contrib.flatpages',
|
||||
'link',
|
||||
'article',
|
||||
'download',
|
||||
'blog',
|
||||
)
|
||||
|
||||
# Add apps/ dir to python path.
|
||||
sys.path.append(join(PROJECT_ABSOLUTE_DIR, "apps"))
|
||||
|
||||
# Override previous settings with values in local_settings.py settings file.
|
||||
try:
|
||||
from local_settings import *
|
||||
except ImportError:
|
||||
debug_msg ="Can't find local_settings.py, using default settings."
|
||||
try:
|
||||
from mod_python import apache
|
||||
apache.log_error("%s" % debug_msg, apache.APLOG_NOTICE)
|
||||
except ImportError:
|
||||
import sys
|
||||
sys.stderr.write("%s\n" % debug_msg)
|
||||
|
After Width: | Height: | Size: 84 B |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 181 B |
|
After Width: | Height: | Size: 338 B |
|
After Width: | Height: | Size: 57 B |
|
After Width: | Height: | Size: 57 B |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 371 B |
|
|
@ -0,0 +1,57 @@
|
|||
/* Scrapy.org style sheet *******************************/
|
||||
|
||||
/* main elements */
|
||||
|
||||
body { margin:0; padding:0; background:url('/site-media/images/main-bg.jpg') repeat-x left top ; font-family:"Lucida Sans", Verdana, Helvetica, sans-serif; font-size:small; color:#333; background-color:#FFF; }
|
||||
a { color:#6e0909; text-decoration:none; border-bottom:1px solid #d78888;}
|
||||
a:hover { color:#f99800; border-bottom:1px solid #f7b7b7; }
|
||||
.clear { clear:both; overflow:hidden; }
|
||||
h1 { background:url('/site-media/images/logo.jpg') no-repeat left top ; text-indent: -5000px; width:545px; height:65px }
|
||||
h2 { font-size:200%; color:#331f0a; margin:0.6em 0pt; font-weight:normal;}
|
||||
blockquote { padding:0px 15px; color:#5b1111; font-size:125%; margin:0;}
|
||||
p { line-height:1.5em; }
|
||||
|
||||
/* structure */
|
||||
#container { width:820px; margin:42px auto 0; }
|
||||
#content { clear:left; margin-top:10px; }
|
||||
#left-column { float:left; width:525px; margin-right:20px}
|
||||
#right-column { float:left; width:274px; margin-top:25px}
|
||||
|
||||
ul#navigation { list-style-type:none; margin:0 0 18px -12px; padding:0;}
|
||||
ul#navigation li { float:left; padding:0 10px; font-size:130%; border-right:1px solid #e57919; }
|
||||
ul#navigation li a { text-decoration:none; border-bottom:1px solid #ffca9b; color:#e57919;}
|
||||
ul#navigation li a:hover { color:#c35012; border-bottom:1px solid #ef994c}
|
||||
|
||||
.box { margin-bottom:15px; background:url('/site-media/images/box-borders-bottom.gif') no-repeat left bottom #4d271c; padding-bottom:5px; }
|
||||
.box.download {background-color:#5b1111; }
|
||||
.box.download p { color:#d18c59; }
|
||||
.box.download a.download { color:#d18c59; background:url('/site-media/images/icon-arrow.gif') no-repeat 2px 2px; padding-left:15px; border-bottom:1px solid #a0595d }
|
||||
.box.download a:hover.download { color:#FFF;}
|
||||
|
||||
.box h3 { padding:10px 10px 0; font-weight:normal; font-size:160%; margin:0.3em 0pt; color:#ffebd2; background:url('/site-media/images/box-borders-top.png') no-repeat left top ;}
|
||||
.box p { padding:0 10px; font-size:90%; line-height:1.2em}
|
||||
|
||||
.box .post { color:#FFF; margin:0pt 13px 5px;
|
||||
padding:0pt 0px 5px; border-bottom:4px solid #462217;}
|
||||
.box .post.last { border-bottom:none; }
|
||||
.box .post p.abstract { padding:0; margin:0; font-size:0.8em; height:1%; line-height:1.3em}
|
||||
.box .post p.author { color:#ffbc97; padding:0 0 0 15px; margin:5px 0px; font-size:0.8em; background:url('/site-media/images/icon-author.gif') no-repeat 2px 3px;}
|
||||
.box .post p.author a { color:#FFF; border-bottom:none }
|
||||
.box .post h4 { display:inline;font-size:1em; font-weight:bold; }
|
||||
.box .post h4 a {color:#ffe114; border-bottom:1px solid #957020; font-size:0.9em}
|
||||
.box .post a.more { font-size:0.8em; color:#ffe114; border-bottom:none;}
|
||||
.box .post a:hover.more { color:#FFF;}
|
||||
|
||||
#footer { margin:45px auto 0; text-align:center; color:#FFF; padding:15px 10px ; background:url('/site-media/images/footer-bg.jpg') repeat-x left top #5b2a16; border-top:1px solid #b5331a;}
|
||||
#footer ul { list-style-type:none; width:41%; margin:0 auto; padding-left:75px; }
|
||||
#footer ul li { float:left; padding:0 10px; font-size:110%; border-right:1px solid #b2c0c9; }
|
||||
ul li.last { border-right:none !important;}
|
||||
#footer li a { text-decoration:none; border-bottom:1px solid #884a2b; color:#FFF;}
|
||||
#footer li a:hover, #footer p a:hover { color:#ffe114; }
|
||||
#footer p {line-height:1.1em; font-size:90%;}
|
||||
#footer p a { color:#fff; }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>{% block title %}Scrapy.org. Scraping framework{% endblock %}</title>
|
||||
|
||||
<link href="{{ MEDIA_URL }}/style/style.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
{% block extrastyles %}{% endblock %}
|
||||
<!--[if IE 6]>
|
||||
<link href="/style/ie60.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
<![endif]-->
|
||||
<!--[if IE 7]>
|
||||
<link href="/style/ie70.css" rel="stylesheet" type="text/css" media="screen" />
|
||||
<![endif]-->
|
||||
|
||||
{% block extrascripts %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<div id="footer">
|
||||
{% block footer %}{% endblock %}
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<p>Got any feedback or suggestions? We're interested in hearing them! <a href="#">Contact us</a>!</p>
|
||||
<p>© 2008 Insophia</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Scrapy - an opensource screen scraping framework for python</h1>
|
||||
|
||||
{% load link_tags %}
|
||||
{% load_links "nav-links" as "nav_links" %}
|
||||
|
||||
{% if nav_links %}
|
||||
<ul id="navigation">
|
||||
{% for link in nav_links %}
|
||||
<li{% if forloop.last %} class="last"{% endif %}><a href="{{ link.address }}">{{ link.text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<div id="content">
|
||||
<div id="left-column">
|
||||
{% block main-content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<div id="right-column">
|
||||
{% load download_tags %}
|
||||
{% load_download_links as "download_links" %}
|
||||
|
||||
{% if download_links %}
|
||||
<div class="box download">
|
||||
<h3>Download Scrapy</h3>
|
||||
|
||||
{% for link in download_links %}
|
||||
<p>{{ link.description }} <a href="{{ link.address }}" class="download">{{ link.text }}</a></p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="box">
|
||||
<h3>Scrapy Weblog</h3>
|
||||
|
||||
<div class="post">
|
||||
<h4><a href="#">post title</a></h4>
|
||||
<p class="author">by <a href="#">Molvo</a> on May 14, 2008</p>
|
||||
<p class="abstract">
|
||||
Nullam ullamcorper, sem quis interdum imperdiet, velit leo convallis ante, eget fringilla lacus
|
||||
interdum imperdiet, velit leo convallis ante, eget fringilla...
|
||||
</p>
|
||||
<a href="#" class="more">» Read More</a>
|
||||
</div>
|
||||
|
||||
<div class="post last">
|
||||
<h4><a href="#">post title</a></h4>
|
||||
<p class="author">by <a href="#">Molvo</a> on May 14, 2008</p>
|
||||
<p class="abstract">
|
||||
Nullam ullamcorper, sem quis interdum imperdiet, velit leo convallis ante, eget fringilla lacus
|
||||
interdum imperdiet, velit leo convallis ante, eget fringilla...
|
||||
</p>
|
||||
<a href="#" class="more">» Read More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
{% load_links "footer-links" as "footer_links" %}
|
||||
{% if footer_links %}
|
||||
<ul>
|
||||
<li style="border-right:none;">Scrapy : </li>
|
||||
{% for link in footer_links %}
|
||||
<li{% if forloop.last %} class="last"{% endif %}><a href="{{ link.address }}">{{ link.text }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{% extends "base_home.html" %}
|
||||
|
||||
{% block title %}{{ block.super }} - Weblog{% endblock %}
|
||||
|
||||
{% block main-content %}
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "base_weblog.html" %}
|
||||
|
||||
{% block main-content %}
|
||||
|
||||
{% load comments comment_utils %}
|
||||
|
||||
<h2>Latest entries</h2>
|
||||
|
||||
{% for object in latest %}
|
||||
<h2><a href="{{ object.get_absolute_url }}">{{ object.headline }}</a></h2>
|
||||
{{ object.body }}
|
||||
<p class="date small">Posted by <strong>{{ object.author }}</strong> on {{ object.pub_date|date:"F j, Y" }}</p>
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{% extends "base_weblog.html" %}
|
||||
|
||||
{% block title %}Weblog | {{ day|date:"F j" }}{% endblock %}
|
||||
|
||||
{% block main-content %}
|
||||
|
||||
<h2>{{ day|date:"F j" }} archive</h2>
|
||||
|
||||
{% for object in object_list %}
|
||||
<h2><a href="{{ object.get_absolute_url }}">{{ object.headline }}</a></h2>
|
||||
<p class="small date">{{ object.pub_date|date:"F j, Y" }}</p>
|
||||
{{ object.body }}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{% extends "base_weblog.html" %}
|
||||
|
||||
{% block title %}Weblog | {{ month|date:"F" }}{% endblock %}
|
||||
|
||||
{% block main-content %}
|
||||
|
||||
<h2>{{ month|date:"F" }} archive</h2>
|
||||
|
||||
{% for object in object_list %}
|
||||
<h2><a href="{{ object.get_absolute_url }}">{{ object.headline }}</a></h2>
|
||||
<p class="small date">{{ object.pub_date|date:"F j, Y" }}</p>
|
||||
{{ object.body }}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{% extends "base_weblog.html" %}
|
||||
|
||||
{% block title %}Weblog | {{ year }}{% endblock %}
|
||||
|
||||
{% block main-content %}
|
||||
|
||||
<h2>{{ year }} archive</h2>
|
||||
|
||||
<ul class="linklist">
|
||||
{% for date in date_list %}
|
||||
<li><a href="{{ date|date:"M"|lower }}/">{{ date|date:"F" }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
{% extends "base_weblog.html" %}
|
||||
|
||||
{% block title %}Weblog | {{ object.headline|escape }}{% endblock %}
|
||||
|
||||
{% block main-content %}
|
||||
|
||||
<h2>{{ object.headline }}</h2>
|
||||
{{ object.body }}
|
||||
<p class="date small">Posted by <strong>{{ object.author }}</strong> on {{ object.pub_date|date:"F j, Y" }}</p>
|
||||
|
||||
{% comment %}
|
||||
{% load comments comment_utils %}
|
||||
{% get_public_free_comment_list for blog.entry object.id as comment_list %}
|
||||
|
||||
<div id="content-secondary">
|
||||
<h2 id="comments">Comments</h2>
|
||||
|
||||
{% for comment in comment_list %}
|
||||
<div class="comment" id="c{{ comment.id }}">
|
||||
<h3>{{ comment.person_name|escape }} <span class="small quiet">{{ comment.submit_date|date:"F j, Y" }} at {{ comment.submit_date|date:"P" }}</span></h3>
|
||||
{{ comment.comment|escape|urlizetrunc:"40"|linebreaks }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if object.comments_enabled %}
|
||||
<h2>Post a comment</h2>
|
||||
{% free_comment_form for blog.entry object.id %}
|
||||
{% else %}
|
||||
<h2>Comments are closed</h2>
|
||||
<p>To prevent spam, comments are no longer allowed after sixty days.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endcomment %}
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{% extends "base_home.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% block main-content %}
|
||||
{% load markup %}
|
||||
{% load article_tags %}
|
||||
|
||||
{% load_main_articles "2" as "articles" %}
|
||||
{% if not articles %}
|
||||
{% load_last_articles "2" as "articles" %}
|
||||
{% endif %}
|
||||
|
||||
{% for article in articles %}
|
||||
<h2>{{ article.title }}</h2>
|
||||
|
||||
{{ article.text|restructuredtext }}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from django.conf.urls.defaults import *
|
||||
from django.views.generic.simple import direct_to_template
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r"^$", direct_to_template, { "template": "home.html" }),
|
||||
(r"^article/", include("article.urls")),
|
||||
(r"^download/", include("download.urls")),
|
||||
(r"^weblog/", include("blog.urls")),
|
||||
|
||||
(r"^admin/", include("django.contrib.admin.urls")),
|
||||
)
|
||||
|
||||
|
||||
if settings.DEBUG: # devel
|
||||
urlpatterns += patterns('',
|
||||
(r"^site-media/(?P<path>.*)$", "django.views.static.serve", { "document_root": settings.MEDIA_ROOT }),
|
||||
)
|
||||