importing old work

This commit is contained in:
James Turk 2010-03-30 10:43:30 -04:00
commit b12fc0b42f
12 changed files with 285 additions and 0 deletions

0
markupwiki/__init__.py Normal file
View File

19
markupwiki/forms.py Normal file
View File

@ -0,0 +1,19 @@
from django import forms
from markupwiki.models import Article, ArticleVersion, PUBLIC, PRIVATE
class ArticleForm(forms.ModelForm):
class Meta:
model = ArticleVersion
fields = ['body', 'body_markup_type']
class StaffModerationForm(forms.ModelForm):
class Meta:
model = Article
fields = ['status']
class ModerationForm(forms.ModelForm):
class Meta:
model = Article
fields = ['status']
status = forms.ChoiceField(choices=((PUBLIC, 'Public'),
(PRIVATE, 'Private')))

41
markupwiki/models.py Normal file
View File

@ -0,0 +1,41 @@
from django.db import models
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from markupfield.fields import MarkupField
PUBLIC, PRIVATE, LOCKED, DELETED = range(4)
ARTICLE_STATUSES = (
(PUBLIC, 'Public'), # public - no restrictions on viewing/editing
(PRIVATE, 'Private'), # private - only creator / admins can view
(LOCKED, 'Locked'), # locked - only admins can edit
(DELETED, 'Deleted'), # deleted - display deleted page
)
class Article(models.Model):
title = models.CharField(max_length=50)
creator = models.ForeignKey(User, related_name='wiki_articles')
status = models.IntegerField(choices=ARTICLE_STATUSES, default=PUBLIC)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('view_article', args=[self.title])
class ArticleVersion(models.Model):
article = models.ForeignKey(Article, related_name='versions')
author = models.ForeignKey(User, related_name='article_versions')
number = models.PositiveIntegerField()
timestamp = models.DateTimeField(auto_now_add=True)
removed = models.BooleanField(default=False)
body = MarkupField()
class Meta:
ordering = ['timestamp']
get_latest_by = 'timestamp'
def __unicode__(self):
return unicode(self.article)
def get_absolute_url(self):
return reverse('article_version', args=[self.article.title, self.number])

View File

@ -0,0 +1,23 @@
<h2>{{article.title}}</h2>
{% if article.locked %} <a href="{% url edit_article article.title %}">edit article</a> {% endif %}
| <a href="{% url article_history article.title %}">view history</a>
{% if form %}
<form method="POST" action="{% url update_article_status article.title %}">
{{ form.as_ul }}
<input type="submit" />
</form>
{% endif %}
<div class="about">
</div>
<div class="body">
{% if article.deleted %}
This article has been deleted.
{% else %}
{{version.body}}
{% endif %}
</div>

View File

@ -0,0 +1,2 @@
{{ table|safe }}

View File

@ -0,0 +1,13 @@
<h2>Article "{{article.title}}" has been deleted</h2>
<a href="{% url edit_article article.title %}">edit article</a>
{% if form %}
<form method="POST" action="{% url update_article_status article.title %}">
{{ form.as_ul }}
<input type="submit" />
</form>
{% endif %}
<p>Once an article has been deleted only a moderator can create an article with the same name.</p>

View File

@ -0,0 +1,10 @@
{% if article %}
<h2>Editing Article "{{title}}"</h2>
{% else %}
<h2>Creating Article "{{title}}"</h2>
{% endif %}
<form method="POST" action=".">
{{ form.as_ul }}
<input type="submit">
</form>

View File

@ -0,0 +1,32 @@
<h2>History {{article.title}}</h2>
<table>
<tr>
<th>Version</th>
<th>Author</th>
<th>Date</th>
<th>Compare From</th>
<th>Compare To</th>
</tr>
<form action="{% url article_diff article.title %}" method="GET">
{% for version in versions %}
<tr>
<td><a href="{{version.get_absolute_url}}">
{% ifequal version.number 0 %}
Initial Version
{% else %}
Revision {{version.number}}
{% endifequal %}
</a></td>
<td>{{version.author}}</td>
<td><a href="{{version.get_absolute_url}}">{{version.timestamp}}</a></td>
<td><input type="radio" name="from" value="{{version.number}}"></td>
<td><input type="radio" name="to" value="{{version.number}}"></td>
</tr>
{% endfor %}
</table>
<input type="submit">
</form>

View File

@ -0,0 +1,5 @@
<h2>This Article is Private</h2>
<div class="body">
Only the author of this article may view it.
</div>

13
markupwiki/urls.py Normal file
View File

@ -0,0 +1,13 @@
from django.conf.urls.defaults import *
WIKI_REGEX = r'^(?P<title>[\w\s]+)'
urlpatterns = patterns('markupwiki.views',
url(WIKI_REGEX + '/$', 'view_article', name='view_article'),
url(WIKI_REGEX + '/edit/$', 'edit_article', name='edit_article'),
url(WIKI_REGEX + '/update_status/$', 'article_status',
name='update_article_status'),
url(WIKI_REGEX + '/history/$', 'article_history', name='article_history'),
url(WIKI_REGEX + '/history/(?P<n>\d+)/$', 'view_article', name='article_version'),
url(WIKI_REGEX + '/diff/$', 'article_diff', name='article_diff'),
)

125
markupwiki/views.py Normal file
View File

@ -0,0 +1,125 @@
from difflib import HtmlDiff
from django.shortcuts import get_object_or_404, render_to_response, redirect
from django.http import HttpResponseForbidden
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
from django.template import RequestContext
from django.utils.functional import wraps
from markupwiki.models import Article, PUBLIC, PRIVATE, DELETED, LOCKED
from markupwiki.forms import ArticleForm, StaffModerationForm, ModerationForm
def title_check(view):
def new_view(request, title, *args, **kwargs):
newtitle = title.replace(' ', '_')
if newtitle != title:
return redirect(request.path.replace(title, newtitle))
else:
return view(request, title, *args, **kwargs)
return wraps(view)(new_view)
@title_check
def view_article(request, title, n=None):
try:
article = Article.objects.get(title=title)
except Article.DoesNotExist:
return redirect('edit_article', title)
if n:
version = article.versions.get(number=n)
else:
version = article.versions.latest()
context = {'article':article, 'version': version}
if request.user.is_staff:
context['form'] = StaffModerationForm(instance=article)
elif request.user == article.creator:
context['form'] = ModerationForm(instance=article)
if article.status == DELETED:
return render_to_response('deleted_article.html', context,
context_instance=RequestContext(request))
elif (article.status == PRIVATE and request.user != article.creator
and not request.user.is_staff):
return render_to_response('private_article.html', context,
context_instance=RequestContext(request))
return render_to_response('article.html', context,
context_instance=RequestContext(request))
@title_check
@login_required
def edit_article(request, title):
try:
article = Article.objects.get(title=title)
except Article.DoesNotExist:
article = None
if article.locked:
return render_to_response('article_locked.html', {'article': article})
if request.method == 'GET':
if article:
version = article.versions.latest()
form = ArticleForm(data={'body':version.body,
'body_markup_type':version.body_markup_type})
else:
form = ArticleForm()
elif request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
if not article:
article = Article.objects.create(title=title,
creator=request.user)
num = 0
else:
num = article.versions.latest().number + 1
version = form.save(False)
version.article = article
version.author = request.user
version.number = num
version.save()
return redirect(article)
return render_to_response('edit_article.html', {'title':title,
'article':article,
'form': form})
@require_POST
@title_check
def article_status(request, title):
article = get_object_or_404(Article, title=title)
status = int(request.POST['status'])
if article.status in (LOCKED, DELETED) or status in (LOCKED, DELETED):
perm_test = lambda u,a: u.is_staff
elif article.status in (PUBLIC, PRIVATE) or status in (PUBLIC, PRIVATE):
perm_test = lambda u,a: u.is_staff or u == a.creator
if perm_test(request.user, article):
article.status = status
article.save()
return redirect(article)
else:
return HttpResponseForbidden('access denied')
@title_check
def article_history(request, title):
article = get_object_or_404(Article, title=title)
versions = article.versions.filter(removed=False)
return render_to_response('history.html', {'article':article,
'versions':versions})
@title_check
def article_diff(request, title):
article = get_object_or_404(Article, title=title)
from_id = int(request.GET['from'])
to_id = int(request.GET['to'])
from_version = article.versions.get(number=from_id)
to_version = article.versions.get(number=to_id)
differ = HtmlDiff()
from_body = from_version.body.raw.split('\n')
to_body = to_version.body.raw.split('\n')
table = differ.make_table(from_body, to_body)
return render_to_response('article_diff.html', {'table':table})

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
Django
-e git+git@github.com:jamesturk/django-markupfield.git#egg=django-markupfield