Permalink
Browse files

Big progress checkpoint, firing escape pod off to github

  • Loading branch information...
1 parent cf758bb commit 299584fc176c606349d33e8659618d2c2e076805 @lmorchard committed Jan 31, 2011
No changes.
View
@@ -0,0 +1,12 @@
+from django.contrib import admin
+
+from .models import Entry
+
+
+class EntryAdmin(admin.ModelAdmin):
+ list_display = (
+ 'id', 'actor_user', 'verb_type', 'object_type', 'target_type',
+ 'title', 'tags', 'published', 'modified',
+ )
+
+admin.site.register(Entry, EntryAdmin)
View
No changes.
View
@@ -0,0 +1,31 @@
+from django import forms
+
+from .models import Entry
+
+from django.utils.translation import ugettext_lazy as _
+
+
+class MyModelForm(forms.ModelForm):
+ pass
+
+
+class MyForm(forms.Form):
+ pass
+
+
+class EntryEditForm(MyModelForm):
+ """Form accepting demo Entrys"""
+
+ class Meta:
+ model = Entry
+ fields = (
+ 'title', 'link', 'tags', 'summary', 'content',
+ )
+
+
+class EntryNewForm(EntryEditForm):
+
+ class Meta(EntryEditForm.Meta):
+ pass
+ #fields = EntryEditForm.Meta.fields + ( 'captcha', 'accept_terms', )
+
No changes.
@@ -0,0 +1,76 @@
+from django.core.management.base import BaseCommand, CommandError
+
+from django.contrib.auth.models import User
+from main.models import Entry
+
+import sys
+from datetime import datetime
+import xml.sax
+from xml.sax.handler import ContentHandler
+
+COUNT_CHUNK = 100
+
+class Command(BaseCommand):
+ help = 'Import bookmarks exported from the Delicious API'
+ args = '<filename>'
+
+ option_list = BaseCommand.option_list + (
+ make_option('--actor', dest='actor', default='lmorchard',
+ help='Name of user as actor'),
+ make_option('--verb', dest='verb', default='post',
+ help='Verb for action (eg. post)'),
+ make_option('--object', dest='object', default='bookmark',
+ help='Object for action (eg. status)'),
+ )
+
+ def handle(self, *args, **options):
+ if len(args) < 1:
+ raise CommandError('Export filename required')
+ user = User.objects.get(username = USERNAME)
+ handler = DeliciousXmlContentHandler(user, options['verb'], options['object'])
+ xml.sax.parse(open(args[0], 'r'), handler)
+
+class DeliciousXmlContentHandler(ContentHandler):
+
+ posts_cnt = 0
+ verb = None
+ object = None
+
+ def __init__(self, user, verb, object):
+ self.user = user
+ self.verb = verb
+ self.object = object
+
+ def startDocument(self):
+ sys.stdout.write("Importing delicious bookmarks for %s\n" % self.user.username)
+
+ def endDocument(self):
+ sys.stdout.write("\nDONE.\n")
+
+ def startElement(self, name, attrs):
+
+ if 'post' == name:
+
+ post = dict(attrs.copy())
+
+ (entry, created) = Entry.objects.get_or_create(
+ actor_user = self.user,
+ verb_type = self.verb,
+ object_type = self.object,
+ link = post['href'],
+ defaults = dict(
+ title = post['description'],
+ summary = post['extended'],
+ tags = post['tag'],
+ )
+ )
+ if created:
+ entry.published = datetime.strptime(post['time'], "%Y-%m-%dT%H:%M:%SZ")
+ entry.save()
+
+ sys.stdout.write('.')
+ self.posts_cnt += 1
+ if (self.posts_cnt % COUNT_CHUNK) == 0:
+ sys.stdout.write('%s\n'%self.posts_cnt)
+ sys.stdout.flush()
+
@@ -0,0 +1,62 @@
+from django.core.management.base import BaseCommand, CommandError
+
+from optparse import make_option
+import feedparser
+
+from django.contrib.auth.models import User
+from main.models import Entry
+
+import sys
+from datetime import datetime
+import xml.sax
+from xml.sax.handler import ContentHandler
+
+COUNT_CHUNK = 100
+
+class Command(BaseCommand):
+ args = '<filename>'
+ help = 'Import status items from an Atom or RSS feed'
+
+ option_list = BaseCommand.option_list + (
+ make_option('--actor', dest='actor', default='lmorchard',
+ help='Name of user as actor'),
+ make_option('--verb', dest='verb', default='post',
+ help='Verb for action (eg. post)'),
+ make_option('--object', dest='object', default='status',
+ help='Object for action (eg. status)'),
+ )
+
+ posts_cnt = 0
+
+ def handle(self, *args, **options):
+ if len(args) < 1:
+ raise CommandError('Feed filename required')
+
+ actor_user = User.objects.get(username = options['actor'])
+
+ d = feedparser.parse(args[0])
+
+ print "Importing %s entries for %s" % ( len(d.entries), actor_user.username )
+
+ for f_entry in d.entries:
+ (entry, created) = Entry.objects.get_or_create(
+ actor_user = actor_user,
+ verb_type = options['verb'],
+ object_type = options['object'],
+ link = f_entry['links'][0]['href'],
+ defaults = dict(
+ title = f_entry['title'],
+ summary = f_entry['summary'],
+ )
+ )
+ if created:
+ entry.published = datetime(*f_entry['published_parsed'][:7])
+ entry.save()
+
+ sys.stdout.write('.')
+ self.posts_cnt += 1
+ if (self.posts_cnt % COUNT_CHUNK) == 0:
+ sys.stdout.write('%s\n'%self.posts_cnt)
+ sys.stdout.flush()
+
+
No changes.
No changes.
View
@@ -0,0 +1,138 @@
+from datetime import datetime
+from time import strftime
+import re
+
+from django.db import models
+from django.db.models import Q
+
+from django.contrib.auth.models import User
+from tagging.models import Tag, TaggedItem
+
+from tagging.utils import parse_tag_input
+from tagging.fields import TagField
+from tagging.models import Tag
+
+from django.template.defaultfilters import slugify
+from django.core.urlresolvers import reverse
+
+from django.utils.translation import ugettext_lazy as _
+
+try:
+ import uuid
+except ImportError:
+ from django.utils import uuid
+
+
+def make_uuid():
+ return str(uuid.uuid4())
+
+
+class EntryManager(models.Manager):
+
+ # TODO: Make these search functions into a mixin?
+
+ # See: http://www.julienphalip.com/blog/2008/08/16/adding-search-django-site-snap/
+ def _normalize_query(self, query_string,
+ findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
+ normspace=re.compile(r'\s{2,}').sub):
+ ''' Splits the query string in invidual keywords, getting rid of unecessary spaces
+ and grouping quoted words together.
+ Example:
+
+ >>> normalize_query(' some random words "with quotes " and spaces')
+ ['some', 'random', 'words', 'with quotes', 'and', 'spaces']
+
+ '''
+ return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
+
+ # See: http://www.julienphalip.com/blog/2008/08/16/adding-search-django-site-snap/
+ def _get_query(self, query_string, search_fields):
+ ''' Returns a query, that is a combination of Q objects. That combination
+ aims to search keywords within a model by testing the given search fields.
+
+ '''
+ query = None # Query to search for every search term
+ terms = self._normalize_query(query_string)
+ for term in terms:
+ or_query = None # Query to search for a given term in each field
+ for field_name in search_fields:
+ q = Q(**{"%s__icontains" % field_name: term})
+ if or_query is None:
+ or_query = q
+ else:
+ or_query = or_query | q
+ if query is None:
+ query = or_query
+ else:
+ query = query & or_query
+ return query
+
+ def search(self, query_string, sort):
+ """Quick and dirty keyword search on submissions"""
+ # TODO: Someday, replace this with something like Sphinx or another real search engine
+ strip_qs = query_string.strip()
+ if not strip_qs:
+ return self.all_sorted(sort).order_by('-published')
+ else:
+ query = self._get_query(strip_qs, ['title', 'link', 'summary',
+ 'content', 'tags', 'meta', ])
+ return self.all_sorted(sort).filter(query).order_by('-published')
+
+ def all_sorted(self, sort=None):
+ """Apply to .all() one of the sort orders supported for views"""
+ queryset = self.all()
+ if sort == 'modified':
+ return queryset.order_by('-modified')
+ else:
+ return queryset.order_by('-published')
+
+
+class Entry(models.Model):
+ objects = EntryManager()
+
+ class Meta:
+ verbose_name_plural = "Entries"
+
+ uuid = models.CharField(max_length=36,
+ default=make_uuid, editable=False)
+
+ slug = models.CharField(max_length=255, blank=True)#, unique=True)
+
+ title = models.CharField(max_length=255, blank=True)#, unique=True)
+ link = models.URLField(blank=True)
+ summary = models.TextField(blank=True)
+ content = models.TextField(blank=True)
+
+ tags = TagField()
+
+ verb_type = models.CharField(max_length=255, blank=True)
+ object_type = models.CharField(max_length=255, blank=True)
+ target_type = models.CharField(max_length=255, blank=True)
+
+ meta = models.TextField(blank=True)
+
+ actor_user = models.ForeignKey(User, blank=True)
+
+ published = models.DateTimeField( _('date published'),
+ auto_now_add=True, blank=False)
+ modified = models.DateTimeField( _('date last modified'),
+ auto_now=True, blank=False)
+
+ def save(self, **kwargs):
+ """Save the entry, updating slug"""
+ self.slug = slugify(self.title)
+ super(Entry,self).save(**kwargs)
+
+ def get_absolute_url(self):
+ #return reverse('main_entry_detail',
+ # kwargs={'username':self.actor_user.username, 'slug':self.slug})
+ return reverse('main.views.entry_detail',
+ kwargs={'username':self.actor_user.username, 'uuid':self.uuid})
+
+
+class EntryAnnotationManager(models.Manager):
+ pass
+
+class EntryAnnotation(models.Model):
+ objects = EntryAnnotationManager()
+
@@ -0,0 +1,9 @@
+{% extends "site_base.html" %}
+
+{% block extra_head %}
+ <link rel="stylesheet" href="{{ STATIC_URL }}main/css/main.css" />
+{% endblock %}
+
+{% block extra_body %}
+ <script src="{{ STATIC_URL }}main/js/main.js"></script>
+{% endblock %}
@@ -0,0 +1,15 @@
+{% extends "main/base.html" %}
+
+{% load i18n %}
+{% load ifsetting_tag %}
+{% load uni_form_tags %}
+
+{% block head_title %}{% trans "Entry" %}{% endblock %}
+
+{% block body %}
+ <h1>{% trans "Entry" %}</h1>
+
+ <ul class="hfeed">
+ {% include "main/includes/hentry.html" %}
+ </ul>
+{% endblock %}
@@ -0,0 +1,36 @@
+{% load i18n %}
+{% load humanize %}
+{% load cache %}
+{% load tagging_tags %}
+
+<li class="hentry verb-{{entry.verb_type}} object-{{entry.object_type}}" id="entry-{{entry.uuid}}">
+ <h4 class="entry-title">
+ {% if not entry.link %}
+ <a href="{{entry.get_absolute_url}}" rel="related">{{ entry.title }}</a>
+ {% else %}
+ <a href="{{entry.link}}" rel="bookmark">{{ entry.title }}</a>
+ {% endif %}
+ </h4>
+ <address class="author">{{ entry.actor_user }}</address>
+ <time class="published" pubdate="pubdate"
+ datetime="{{entry.published|date:"Y-m-d\TH:i:sO"}}"
+ title="{{entry.published|date:"Y-m-d\TH:i:sO"}}">
+ <a rel="bookmark" href="{{entry.get_absolute_url}}">{{entry.published|date:"DATETIME_FORMAT"}}</a>
+ </time>
+ {% if entry.summary and entry.summary != entry.title %}
+ <div class="entry-summary">{{entry.summary}}</div>
+ {% endif %}
+ {% if entry.content and entry.content != entry.title and entry.content != entry.summary %}
+ <div class="entry-content">{{entry.content}}</div>
+ {% endif %}
+ {% tags_for_object entry as tags %}
+ {% if tags %}
+ <ul class="tags">
+ {% for tag in tags %}
+ <li>
+ <a class="tag" href="{% url main_profile_tag username=entry.actor_user.username tag_name=tag.name %}">{{ tag.name }}</a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+</li>
Oops, something went wrong. Retry.

0 comments on commit 299584f

Please sign in to comment.