Commit 9f1b3a98 by Bridger Maxwell

Merge branch 'master' of git://github.com/benjaoming/django-wiki

parents 341db91d c3303e15
django-wiki django-wiki
=========== ===========
*Last update: 2012-08-08* *Last update: 2012-08-12*
Demo here, sign up for an account to see the notification system. Demo here, sign up for an account to see the notification system.
...@@ -10,7 +10,7 @@ Demo here, sign up for an account to see the notification system. ...@@ -10,7 +10,7 @@ Demo here, sign up for an account to see the notification system.
NB!! *THIS IS A WORK IN PROGRESS* NB!! *THIS IS A WORK IN PROGRESS*
--------------------------------- ---------------------------------
This is where it all begins. In less than *3* weeks we should have a wiki system appealing to any kind of Django developer out there. Here is the manifest (so far): This is where it all begins. In *1* week we should have a wiki system appealing to any kind of Django developer out there. Here is the manifest (so far):
* **Be pluggable and light-weight.** Don't integrate optional features in the core. * **Be pluggable and light-weight.** Don't integrate optional features in the core.
* **Be open.** Make an extension API that allows the ecology of the wiki to grow. After all, Wikipedia consists of some [680 extensions](http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/) written for MediaWiki. * **Be open.** Make an extension API that allows the ecology of the wiki to grow. After all, Wikipedia consists of some [680 extensions](http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/) written for MediaWiki.
...@@ -21,19 +21,63 @@ This is where it all begins. In less than *3* weeks we should have a wiki system ...@@ -21,19 +21,63 @@ This is where it all begins. In less than *3* weeks we should have a wiki system
Installation Installation
------------ ------------
pip install git+git://github.com/benjaoming/django-wiki.git ### Install
After that, add `'wiki'` and `'django_notify'` to `settings.INSTALLED_APPS`. Install directly from Github, since there is no release yet:
`pip install git+git://github.com/benjaoming/django-wiki.git`
### Configure `settings.INSTALLED_APPS`
Make sure that the following is present:
'wiki',
'wiki.plugins.attachments',
'wiki.plugins.notifications',
'wiki.plugins.images',
'south',
'django_notify',
'mptt',
'sekizai',
'django.contrib.humanize',
### Database
To sync and create tables, do:
python manage.py syncdb
python manage.py migrate
### Configure `settings.TEMPLATE_CONTEXT_PROCESSORS`
Add `'sekizai.context_processors.sekizai'` to `settings.TEMPLATE_CONTEXT_PROCESSORS`.
### Include urlpatterns
To integrate the wiki to your existing application, you shoud add the following lines at the end of your project's `urls.py`.
from wiki.urls import get_pattern as get_wiki_pattern
from django_notify.urls import get_pattern as get_notify_pattern
urlpatterns += patterns('',
(r'^notify/', get_notify_pattern()),
(r'', get_wiki_pattern())
)
Please use these function calls rather than writing your own include() call - the url namespaces aren't supposed to be customized.
The above line puts the wiki in */* so it's important to put it at the end of your urlconf. You can also put it in */wiki* by putting `'^wiki/'` as the pattern.
Plugins Plugins
------------ ------------
Add the following to your `settings.INSTALLED_APPS` to enable some nifty plugins: Add/remove the following to your `settings.INSTALLED_APPS` to enable/disable the core plugins:
* `'wiki.plugins.attachments'` * `'wiki.plugins.attachments'`
* `'wiki.plugins.images'` * `'wiki.plugins.images'`
* `'wiki.plugins.notifications'` * `'wiki.plugins.notifications'`
The notifications plugin is mandatory for an out-of-the-box installation. You can safely remove it from INSTALLED_APPS if you also override the **wiki/base.html** template.
Background Background
---------- ----------
...@@ -64,9 +108,17 @@ So far the dependencies are: ...@@ -64,9 +108,17 @@ So far the dependencies are:
* [django-mptt>=0.5](https://github.com/django-mptt/django-mptt) * [django-mptt>=0.5](https://github.com/django-mptt/django-mptt)
* [django-sekizai](https://github.com/ojii/django-sekizai/) * [django-sekizai](https://github.com/ojii/django-sekizai/)
Development
------------
In a your Git fork, run `pip install -r requirements.txt` to install the requirements.
The folder **testproject/** contains a pre-configured django project and an sqlite database. Login for django admin is *admin:admin*. This project should always be maintained, although the sqlite database will be deleted very soon to avoid unnecessary conflicts.
Acknowledgements Acknowledgements
---------------- ----------------
* The people at [edX](http://www.edxonline.org/) & MIT for finding and supporting the project both financially and with ideas. * The people at [edX](http://www.edxonline.org/) & MIT for finding and supporting the project both financially and with ideas.
* [django-cms](https://github.com/divio/django-cms) for venturing where no django app has gone before in terms of well-planned features and high standards. It's a very big inspiration. * [django-cms](https://github.com/divio/django-cms) for venturing where no django app has gone before in terms of well-planned features and high standards. It's a very big inspiration.
* [django-mptt](https://github.com/django-mptt/django-mptt), a wonderful utility for inexpensively using tree structures in Django with a relational database backend.
...@@ -5,13 +5,10 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns ...@@ -5,13 +5,10 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin from django.contrib import admin
admin.autodiscover() admin.autodiscover()
from wiki.urls import get_pattern as wiki_pattern
from django_notify.urls import get_pattern as notify_pattern
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^notify/', include(notify_pattern())), url(r'^notify/', include('django_notify.urls', namespace='notify')),
) )
if settings.DEBUG: if settings.DEBUG:
...@@ -21,5 +18,7 @@ if settings.DEBUG: ...@@ -21,5 +18,7 @@ if settings.DEBUG:
'document_root': settings.MEDIA_ROOT, 'document_root': settings.MEDIA_ROOT,
}), }),
) )
urlpatterns += patterns('', url(r'', include(wiki_pattern())),) from wiki.urls import get_pattern as get_wiki_pattern
\ No newline at end of file from django_notify.urls import get_pattern as get_notify_pattern
urlpatterns += patterns('', (r'^notify/', get_notify_pattern()), (r'', get_wiki_pattern()))
\ No newline at end of file
...@@ -15,9 +15,6 @@ class Article(models.Model): ...@@ -15,9 +15,6 @@ class Article(models.Model):
objects = managers.ArticleManager() objects = managers.ArticleManager()
title = models.CharField(max_length=512, verbose_name=_(u'title'),
null=False, blank=False, help_text=_(u'Initial title of the article. '
'May be overridden with revision titles.'))
current_revision = models.OneToOneField('ArticleRevision', current_revision = models.OneToOneField('ArticleRevision',
verbose_name=_(u'current revision'), verbose_name=_(u'current revision'),
blank=True, null=True, related_name='current_set', blank=True, null=True, related_name='current_set',
...@@ -70,10 +67,20 @@ class Article(models.Model): ...@@ -70,10 +67,20 @@ class Article(models.Model):
return False return False
def decendant_objects(self): def decendant_objects(self):
for obj in self.objectforarticle_set.filter(is_mptt=True): """NB! This generator is expensive, so use it with care!!"""
for decendant in obj.get_decendants(): for obj in self.articleforobject_set.filter(is_mptt=True):
for decendant in obj.content_object.get_decendants():
yield decendant yield decendant
def get_children(self, max_num=None):
"""NB! This generator is expensive, so use it with care!!"""
cnt = 0
for obj in self.articleforobject_set.filter(is_mptt=True):
for child in obj.content_object.get_children():
cnt += 1
if cnt > max_num: return
yield child
# All recursive permission methods will use decendant_objects to access # All recursive permission methods will use decendant_objects to access
# generic relations and check if they are using MPTT and have INHERIT_PERMISSIONS=True # generic relations and check if they are using MPTT and have INHERIT_PERMISSIONS=True
def set_permissions_recursive(self): def set_permissions_recursive(self):
...@@ -130,7 +137,7 @@ class Article(models.Model): ...@@ -130,7 +137,7 @@ class Article(models.Model):
def __unicode__(self): def __unicode__(self):
if self.current_revision: if self.current_revision:
return self.current_revision.title return self.current_revision.title
return self.title return _(u'Article without content (%(id)d)') % {'id': self.id}
class Meta: class Meta:
app_label = settings.APP_LABEL app_label = settings.APP_LABEL
...@@ -264,8 +271,6 @@ class ArticleRevision(BaseRevisionMixin, models.Model): ...@@ -264,8 +271,6 @@ class ArticleRevision(BaseRevisionMixin, models.Model):
# If I'm saved from Django admin, then article.current_revision is me! # If I'm saved from Django admin, then article.current_revision is me!
self.article.current_revision = self self.article.current_revision = self
self.article.save() self.article.save()
if not self.title:
self.title = self.article.title
class Meta: class Meta:
app_label = settings.APP_LABEL app_label = settings.APP_LABEL
......
...@@ -24,7 +24,8 @@ ...@@ -24,7 +24,8 @@
</div> </div>
</div> </div>
<p style="margin-top: 20px;"><em>{% trans "Article last modified:" %} {{ article.current_revision.modified }}</em></p>
{% endblock %} {% endblock %}
{% block footer_prepend %}
<p style="margin-bottom: 10px;"><em>{% trans "This article was last modified:" %} {{ article.current_revision.modified }}</em></p>
{% endblock %}
...@@ -127,10 +127,12 @@ ...@@ -127,10 +127,12 @@
<p>Use this document as a way to quick start any new project.<br> All you get is this message and a barebones HTML document.</p> <p>Use this document as a way to quick start any new project.<br> All you get is this message and a barebones HTML document.</p>
{% endblock %} {% endblock %}
<div style="padding: 50px 0;"> <div style="padding: 30px 0;">
<footer> <footer>
<hr /> <hr />
<a href="https://github.com/benjaoming/django-wiki" class="pull-right"><img src="{{ STATIC_URL }}wiki/img/github_icon.png" /></a> <a href="https://github.com/benjaoming/django-wiki" class="pull-right"><img src="{{ STATIC_URL }}wiki/img/github_icon.png" /></a>
{% block footer_prepend %}
{% endblock %}
<p>Powered by <a href="http://www.django-wiki.org">django-wiki</a>, an open source application under the <a href="http://www.gnu.org/licenses/quick-guide-gplv3.html">GPLv3</a> license. Let knowledge be the cure.</p> <p>Powered by <a href="http://www.django-wiki.org">django-wiki</a>, an open source application under the <a href="http://www.gnu.org/licenses/quick-guide-gplv3.html">GPLv3</a> license. Let knowledge be the cure.</p>
<div style="clear: both"></div> <div style="clear: both"></div>
</footer> </footer>
......
{% extends "wiki/base.html" %} {% extends "wiki/base.html" %}
{% load wiki_tags i18n %} {% load wiki_tags i18n %}
{% block wiki_body %} {% block wiki_body %}
{% if revision %}
<div class="alert alert-info"> {% if revision %}
<strong>{% trans "Previewing revision" %}:</strong> {{ revision.created }} (#{{ revision.revision_number }}) by {% if revision.user %}{{ revision.user }}{% else %}{% if user|is_moderator %}{{ revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} <div class="alert alert-info">
</div> <strong>{% trans "Previewing revision" %}:</strong> {{ revision.created }} (#{{ revision.revision_number }}) by {% if revision.user %}{{ revision.user }}{% else %}{% if user|is_moderator %}{{ revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
{% endif %} </div>
{% if merge %} {% endif %}
<div class="alert alert-info">
<strong>{% trans "Previewing merge between" %}:</strong> {% if merge %}
{{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} <div class="alert alert-info">
<strong>{% trans "and" %}</strong> <strong>{% trans "Previewing merge between" %}:</strong>
{{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} {{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
</div> <strong>{% trans "and" %}</strong>
{% endif %} {{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
<h1 class="page-header">{{ title }}</h1> </div>
{% wiki_render article content %} {% endif %}
<h1 class="page-header">{{ title }}</h1>
{% wiki_render article content %}
{% endblock %} {% endblock %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment