initial commit

This commit is contained in:
Jeremy Carbaugh
2009-03-27 13:38:19 -04:00
commit 539bdb04ac
17 changed files with 570 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
*.pyc
+5
View File
@@ -0,0 +1,5 @@
# Changelog for django-wordpress
## 0.1.0
* initial release
+10
View File
@@ -0,0 +1,10 @@
Copyright (c) 2009, Sunlight Foundation
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Sunlight Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+4
View File
@@ -0,0 +1,4 @@
include LICENSE
include README.markdown
recursive-include wordpress *.py
recursive-include wordpress/templates *.html
+54
View File
@@ -0,0 +1,54 @@
# django-wordpress
Models and views for reading a WordPress database. Compatible with WordPress version 2.6.1.
These models are meant to be read-only. Writing is enabled by adding *WP_READ_ONLY = False* to settings.py. None of the WordPress specific logic is included while writing to the database so there is a good chance you will break your WordPress install if you enable writing.
The default table prefix is *wp*. To change the table prefix, add *WP_TABLE_PREFIX = 'yourprefix'* to settings.py.
Default templates are provided only for development purposes! Please override these with customized templates for your application.
django-wordpress is a project of Sunlight Foundation (c) 2009.
Writen by Jeremy Carbaugh <jcarbaugh@sunlightfoundation.com>
All code is under a BSD-style license, see LICENSE for details.
Source: http://github.com/sunlightlabs/django-wordpress/
## Requirements
python >= 2.4
django >= 1.0
## Installation
To install run
python setup.py install
which will install the application into python's site-packages directory.
## Quick Setup
### settings.py
Add to INSTALLED_APPS:
wordpress
### urls.py
Include the following in urls.py.
url(r'^path/to/blog/', include('')),
## Help!
The term/taxonomy support is quite shoddy. Any help in that area would be greatly appreciated.
+26
View File
@@ -0,0 +1,26 @@
from distutils.core import setup
long_description = open('README.markdown').read()
setup(
name='django-wordpress',
version="0.1",
description='Django models and views for a WordPress database',
long_description=long_description,
author='Jeremy Carbaugh',
author_email='jcarbaugh@sunlightfoundation.com',
url='http://github.com/sunlightlabs/django-wordpress/',
packages=['wordpress'],
package_data={'wordpress': ['templates/wordpress/*.html']},
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Environment :: Web Environment',
],
license='BSD License',
platforms=["any"],
)
View File
+45
View File
@@ -0,0 +1,45 @@
from django.contrib import admin
from wordpress.models import Comment, Link, Post, PostMeta, Taxonomy, Term, User, UserMeta
class CommentAdmin(admin.ModelAdmin):
list_display = ('id','post','author_name','post_date')
list_filter = ('comment_type','approved')
search_fields = ('author_name','author_email','post__title')
class LinkAdmin(admin.ModelAdmin):
list_display = ('id','name','url','description')
list_filter = ('visible',)
search_fields = ('name','url','description')
class PostMetaInline(admin.TabularInline):
model = PostMeta
class PostAdmin(admin.ModelAdmin):
inlines = (PostMetaInline,)
list_display = ('id','title','author','post_date')
list_filter = ('status','post_type','comment_status','ping_status','author')
search_fields = ('title',)
class UserMetaInline(admin.TabularInline):
model = UserMeta
class UserAdmin(admin.ModelAdmin):
inlines = (UserMetaInline,)
list_display = ('id','display_name','email','status')
list_filter = ('status',)
search_fields = ('login','username','display_name','email')
class TaxonomyAdmin(admin.ModelAdmin):
list_display = ('id','name','term')
list_filter = ('name',)
class TermAdmin(admin.ModelAdmin):
list_display = ('id','name')
search_fields = ('name',)
admin.site.register(Comment, CommentAdmin)
admin.site.register(Link, LinkAdmin)
admin.site.register(Post, PostAdmin)
admin.site.register(Taxonomy, TaxonomyAdmin)
admin.site.register(Term, TermAdmin)
admin.site.register(User, UserAdmin)
+362
View File
@@ -0,0 +1,362 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import connection, models
from django.db.models import signals
from django.http import HttpResponseRedirect
import re
STATUS_CHOICES = (
('closed', 'closed'),
('open', 'open'),
)
POST_STATUS_CHOICES = (
('draft', 'draft'),
('inherit', 'inherit'),
('private', 'private'),
('publish', 'publish'),
)
POST_TYPE_CHOICES = (
('attachment','attachment'),
('page','page'),
('post','post'),
('revision','revision'),
)
USER_STATUS_CHOICES = (
(0, "active"),
)
READ_ONLY = getattr(settings, "WP_READ_ONLY", True)
TABLE_PREFIX = getattr(settings, "WP_TABLE_PREFIX", "wp")
#
# Exceptions
#
class WordPressException(Exception):
"""
Exception that is thrown when attempting to save a read-only object.
"""
pass
#
# Base models
#
class WordPressModel(models.Model):
"""
Base model for all WordPress objects.
Overrides save and delete methods to enforce read-only setting.
"""
class Meta:
abstract = True
def _get_object(self, model, obj_id):
try:
return model.objects.get(pk=obj_id)
except model.DoesNotExist:
pass
def save(self, override=False):
if READ_ONLY and not override:
raise WordPressException, "object is read-only"
super(WordPressModel, self).save()
def delete(self, override=False):
if READ_ONLY and not override:
raise WordPressException, "object is read-only"
super(WordPressModel, self).delete()
#
# WordPress models
#
class User(WordPressModel):
"""
User object. Referenced by Posts, Comments, and Links
"""
login = models.CharField(max_length=60, db_column='user_login')
password = models.CharField(max_length=64, db_column='user_pass')
username = models.CharField(max_length=255, db_column='user_nicename')
email = models.CharField(max_length=100, db_column='user_email')
url = models.URLField(max_length=100, db_column='user_url', verify_exists=False)
date_registered = models.DateTimeField(auto_now_add=True, db_column='user_registered')
activation_key = models.CharField(max_length=60, db_column='user_activation_key')
status = models.IntegerField(default=0, choices=USER_STATUS_CHOICES, db_column='user_status')
display_name = models.CharField(max_length=255, db_column='display_name')
class Meta:
db_table = '%s_users' % TABLE_PREFIX
ordering = ["display_name"]
def __unicode__(self):
return self.display_name
class UserMeta(WordPressModel):
"""
Meta information about a user.
"""
id = models.IntegerField(db_column='umeta_id', primary_key=True)
user = models.ForeignKey(User, related_name="meta", db_column='user_id')
key = models.CharField(max_length=255, db_column='meta_key')
value = models.TextField(db_column='meta_value')
class Meta:
db_table = '%s_usermeta' % TABLE_PREFIX
def __unicode__(self):
return u"%s: %s" % (self.key, self.value)
class Link(WordPressModel):
"""
An external link.
"""
id = models.IntegerField(db_column='link_id', primary_key=True)
url = models.URLField(max_length=255, verify_exists=False, db_column='link_url')
name = models.CharField(max_length=255, db_column='link_name')
image = models.CharField(max_length=255, db_column='link_image')
target = models.CharField(max_length=25, db_column='link_target')
category_id = models.IntegerField(default=0, db_column='link_category')
description = models.CharField(max_length=255, db_column='link_description')
visible = models.CharField(max_length=20, db_column='link_visible')
owner = models.ForeignKey(User, related_name='links', db_column='link_owner')
rating = models.IntegerField(default=0, db_column='link_rating')
updated = models.DateTimeField(blank=True, null=True, db_column='link_updated')
rel = models.CharField(max_length=255, db_column='link_rel')
notes = models.TextField(db_column='link_notes')
rss = models.CharField(max_length=255, db_column='link_rss')
class Meta:
db_table = '%s_links' % TABLE_PREFIX
def __unicode__(self):
return u"%s %s" % (self.name, self.url)
def is_visible(self):
return self.visible == 'Y'
class PostManager(models.Manager):
"""
Provides convenience methods for filtering posts by status.
"""
def _by_status(self, status, post_type='post'):
return Post.objects.filter(status=status, post_type=post_type)
def drafts(self, post_type='post'):
return self._by_status('draft', post_type)
def private(self, post_type='post'):
return self._by_status('private', post_type)
def published(self, post_type='post'):
return self._by_status('publish', post_type)
def term(self, term, taxonomy='post_tag'):
tx = Taxonomy.objects.get(name=taxonomy, term__name=term)
table = '%s_term_relationships' % TABLE_PREFIX
sql = """SELECT object_id FROM """ + table + """ WHERE term_taxonomy_id = %s"""
cursor = connection.cursor()
cursor.execute(sql, [tx.pk,])
pids = [row[0] for row in cursor.fetchall()]
return Post.objects.published().filter(pk__in=pids)
class Post(WordPressModel):
"""
The mother lode.
The WordPress post.
"""
objects = PostManager()
# post data
guid = models.CharField(max_length=255)
post_type = models.CharField(max_length=20, choices=POST_TYPE_CHOICES)
status = models.CharField(max_length=20, db_column='post_status', choices=POST_STATUS_CHOICES)
title = models.TextField(db_column='post_title')
slug = models.SlugField(max_length=200, db_column="post_name")
author = models.ForeignKey(User, related_name='posts', db_column='post_author')
excerpt = models.TextField(db_column='post_excerpt')
content = models.TextField(db_column='post_content')
content_filtered = models.TextField(db_column='post_content_filtered')
post_date = models.DateTimeField(db_column='post_date_gmt')
modified = models.DateTimeField(db_column='post_modified_gmt')
# comment stuff
comment_status = models.CharField(max_length=20, choices=STATUS_CHOICES)
comment_count = models.IntegerField(default=0)
# ping stuff
ping_status = models.CharField(max_length=20, choices=STATUS_CHOICES)
to_ping = models.TextField()
pinged = models.TextField()
# statuses
password = models.CharField(max_length=20, db_column="post_password")
category_id = models.IntegerField(db_column='post_category')
# other various lame fields
parent = models.ForeignKey('self', related_name="children", db_column="post_parent", blank=True, null=True)
menu_order = models.IntegerField(default=0)
mime_type = models.CharField(max_length=100, db_column='post_mime_type')
category_cache = None
tag_cache = None
class Meta:
db_table = '%s_posts' % TABLE_PREFIX
ordering = ["-post_date"]
def __unicode__(self):
return self.title
def categories(self):
if not self.category_cache:
taxonomy = "category"
self.category_cache = self._get_terms(taxonomy)
return self.category_cache
def get_absolute_url(self):
year = self.post_date.year
month = self.post_date.month
day = self.post_date.day
slug = self.slug
print reverse('wp_object_detail', args=(year, month, day, slug))
return reverse('wp_object_detail', args=(year, month, day, slug))
"""
@models.permalink
def get_absolute_url(self):
params = {
"year": self.post_date.year,
"month": self.post_date.month,
"day": self.post_date.day,
"slug": self.slug,
}
return ('wp_object_detail', (), params)
"""
"""
def parent(self):
return self._get_object(Post, self.parent_id)
"""
def tags(self):
if not self.tag_cache:
taxonomy = "post_tag"
self.tag_cache = self._get_terms(taxonomy)
return self.tag_cache
def _get_terms(self, taxonomy):
table = '%s_term_relationships' % TABLE_PREFIX
sql = """SELECT term_taxonomy_id FROM """ + table + """ WHERE object_id = %s ORDER BY term_order"""
cursor = connection.cursor()
cursor.execute(sql, [self.id,])
ttids = [row[0] for row in cursor.fetchall()]
return Term.objects.filter(taxonomies__name=taxonomy, taxonomies__pk__in=ttids)
class PostMeta(WordPressModel):
"""
Post meta data.
"""
id = models.IntegerField(db_column='meta_id', primary_key=True)
post = models.ForeignKey(Post, related_name='meta', db_column='post_id')
key = models.CharField(max_length=255, db_column='meta_key')
value = models.TextField(db_column='meta_value')
class Meta:
db_table = '%s_postmeta' % TABLE_PREFIX
def __unicode__(self):
return u"%s: %s" % (self.key, self.value)
class Comment(WordPressModel):
"""
Comments to Posts.
"""
id = models.IntegerField(db_column='comment_id', primary_key=True)
post = models.ForeignKey(Post, related_name="comments", db_column="comment_post_id")
user_id = models.IntegerField(db_column='user_id', default=0)
#user = models.ForeignKey(User, related_name="comments", blank=True, null=True, default=0 )
parent_id = models.IntegerField(default=0, db_column='comment_parent')
# author fields
author_name = models.CharField(max_length=255, db_column='comment_author')
author_email = models.EmailField(max_length=100, db_column='comment_author_email')
author_url = models.URLField(verify_exists=False, db_column='comment_author_url')
author_ip = models.IPAddressField(db_column='comment_author_ip')
# comment data
post_date = models.DateTimeField(db_column='comment_date_gmt')
content = models.TextField(db_column='comment_content')
karma = models.IntegerField(default=0, db_column='comment_karma')
approved = models.CharField(max_length=20, db_column='comment_approved')
# other stuff
agent = models.CharField(max_length=255, db_column='comment_agent')
comment_type = models.CharField(max_length=20)
class Meta:
db_table = '%s_comments' % TABLE_PREFIX
ordering = ['-post_date']
def __unicode__(self):
return u"%s on %s" % (self.author_name, self.post.title)
def get_absolute_url(self):
return "%s#comment-%i" % (self.post.get_absolute_url(), self.pk)
def parent(self):
return self._get_object(Comment, self.parent_id)
"""
def user(self):
return self._get_object(User, self.user_id)
"""
def is_approved(self):
return self.approved == '1'
def is_spam(self):
return self.approved == 'spam'
class Term(WordPressModel):
id = models.IntegerField(db_column='term_id', primary_key=True)
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200)
group = models.IntegerField(default=0, db_column='term_group')
class Meta:
db_table = '%s_terms' % TABLE_PREFIX
ordering = ['name',]
def __unicode__(self):
return self.name
class Taxonomy(WordPressModel):
id = models.IntegerField(db_column='term_taxonomy_id', primary_key=True)
term = models.ForeignKey(Term, related_name='taxonomies', blank=True, null=True)
#term_id = models.IntegerField()
name = models.CharField(max_length=32, db_column='taxonomy')
description = models.TextField()
parent_id = models.IntegerField(default=0, db_column='parent')
count = models.IntegerField(default=0)
class Meta:
db_table = '%s_term_taxonomy' % TABLE_PREFIX
ordering = ['name',]
def __unicode__(self):
try:
term = self.term
except Term.DoesNotExist:
term = ''
return u"%s: %s" % (self.name, term)
def parent(self):
return self._get_object(Taxonomy, self.parent_id)
#def term(self):
# return self._get_object(Term, self.term_id)
@@ -0,0 +1 @@
{{ latest }}
@@ -0,0 +1 @@
{{ post_list }}
@@ -0,0 +1 @@
{{ post_list }}
@@ -0,0 +1,5 @@
<ol>
{% for date in date_list %}
<li><a href="{% url wp_archive_month date.year,date.month %}">{{ date|date:"F" }}</a></li>
{% endfor %}
</ol>
@@ -0,0 +1 @@
{{ post }}
@@ -0,0 +1 @@
{{ post_list }}
+10
View File
@@ -0,0 +1,10 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('wordpress.views',
url(r'^taxonomy/(?P<taxonomy>term|category)/(?P<term>[\w-]+)/$', 'taxonomy', name='wp_taxonomy'),
url(r'^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/$', 'object_detail', name='wp_object_detail'),
url(r'^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', 'archive_day', name='wp_archive_day'),
url(r'^(?P<year>\d{4})/(?P<month>\d{1,2})/$', 'archive_month', name='wp_archive_month'),
url(r'^(?P<year>\d{4})/$', 'archive_year', name='wp_archive_year'),
url(r'^$', 'archive_index', name='wp_archive_index'),
)
+43
View File
@@ -0,0 +1,43 @@
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.views.generic import date_based
from wordpress.models import Post
TAXONOMIES = {
'term': 'post_tag',
'category': 'category',
'link_category': 'link_category',
}
def object_detail(request, year, month, day, slug):
return date_based.object_detail(request, queryset=Post.objects.published(),
date_field='post_date', year=year, month=month, month_format="%m",
day=day, slug=slug, slug_field='slug', template_object_name='post')
def archive_day(request, year, month, day):
return date_based.archive_day(request, queryset=Post.objects.published(),
date_field='post_date', year=year, month=month, month_format="%m",
day=day, template_object_name='post')
def archive_month(request, year, month):
return date_based.archive_month(request, queryset=Post.objects.published(),
date_field='post_date', year=year, month=month, month_format="%m",
template_object_name='post')
def archive_year(request, year):
return date_based.archive_year(request, queryset=Post.objects.published(),
date_field='post_date', year=year)
def archive_index(request):
p = request.GET.get('p', None)
if p:
post = Post.objects.get(pk=p)
return HttpResponseRedirect(post.get_absolute_url())
return date_based.archive_index(request,
queryset=Post.objects.published(), date_field='post_date')
def taxonomy(request, taxonomy, term):
taxonomy = TAXONOMIES.get(taxonomy, None)
if taxonomy:
posts = Post.objects.term(term, taxonomy=taxonomy)
return render_to_response('wordpress/post_term.html', {'post_list': posts})