Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
django-wiki
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
django-wiki
Commits
e56a78a7
Commit
e56a78a7
authored
Nov 06, 2014
by
paul
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
python_2_unicode_compatible decorateur
parent
0d10395f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
55 additions
and
25 deletions
+55
-25
wiki/admin.py
+1
-1
wiki/models/article.py
+20
-13
wiki/models/pluginbase.py
+19
-4
wiki/models/urlpath.py
+15
-7
No files found.
wiki/admin.py
View file @
e56a78a7
...
@@ -69,7 +69,7 @@ class URLPathAdmin(MPTTModelAdmin):
...
@@ -69,7 +69,7 @@ class URLPathAdmin(MPTTModelAdmin):
list_filter
=
(
'site'
,
'articles__article__current_revision__deleted'
,
list_filter
=
(
'site'
,
'articles__article__current_revision__deleted'
,
'articles__article__created'
,
'articles__article__created'
,
'articles__article__modified'
)
'articles__article__modified'
)
list_display
=
(
'__
unicode
__'
,
'article'
,
'get_created'
)
list_display
=
(
'__
str
__'
,
'article'
,
'get_created'
)
def
get_created
(
self
,
instance
):
def
get_created
(
self
,
instance
):
return
instance
.
article
.
created
return
instance
.
article
.
created
...
...
wiki/models/article.py
View file @
e56a78a7
...
@@ -7,6 +7,7 @@ from django.contrib.auth.models import Group
...
@@ -7,6 +7,7 @@ from django.contrib.auth.models import Group
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.db
import
models
from
django.db
import
models
from
django.db.models.signals
import
post_save
,
pre_delete
from
django.db.models.signals
import
post_save
,
pre_delete
from
django.utils.encoding
import
python_2_unicode_compatible
from
django.utils.safestring
import
mark_safe
from
django.utils.safestring
import
mark_safe
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
...
@@ -17,6 +18,7 @@ from wiki import managers
...
@@ -17,6 +18,7 @@ from wiki import managers
from
mptt.models
import
MPTTModel
from
mptt.models
import
MPTTModel
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
@python_2_unicode_compatible
class
Article
(
models
.
Model
):
class
Article
(
models
.
Model
):
objects
=
managers
.
ArticleManager
()
objects
=
managers
.
ArticleManager
()
...
@@ -139,7 +141,7 @@ class Article(models.Model):
...
@@ -139,7 +141,7 @@ class Article(models.Model):
def
get_for_object
(
cls
,
obj
):
def
get_for_object
(
cls
,
obj
):
return
ArticleForObject
.
objects
.
get
(
object_id
=
obj
.
id
,
content_type
=
ContentType
.
objects
.
get_for_model
(
obj
))
.
article
return
ArticleForObject
.
objects
.
get
(
object_id
=
obj
.
id
,
content_type
=
ContentType
.
objects
.
get_for_model
(
obj
))
.
article
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
if
self
.
current_revision
:
if
self
.
current_revision
:
return
self
.
current_revision
.
title
return
self
.
current_revision
.
title
obj_name
=
_
(
'Article without content (
%(id)
d)'
)
%
{
'id'
:
self
.
id
}
obj_name
=
_
(
'Article without content (
%(id)
d)'
)
%
{
'id'
:
self
.
id
}
...
@@ -184,17 +186,17 @@ class Article(models.Model):
...
@@ -184,17 +186,17 @@ class Article(models.Model):
else
:
else
:
return
reverse
(
'wiki:get'
,
kwargs
=
{
'article_id'
:
self
.
id
})
return
reverse
(
'wiki:get'
,
kwargs
=
{
'article_id'
:
self
.
id
})
class
ArticleForObject
(
models
.
Model
):
class
ArticleForObject
(
models
.
Model
):
objects
=
managers
.
ArticleFkManager
()
objects
=
managers
.
ArticleFkManager
()
article
=
models
.
ForeignKey
(
'Article'
,
on_delete
=
models
.
CASCADE
)
article
=
models
.
ForeignKey
(
'Article'
,
on_delete
=
models
.
CASCADE
)
# Same as django.contrib.comments
# Same as django.contrib.comments
content_type
=
models
.
ForeignKey
(
ContentType
,
content_type
=
models
.
ForeignKey
(
ContentType
,
verbose_name
=
_
(
'content type'
),
verbose_name
=
_
(
'content type'
),
related_name
=
"content_type_set_for_
%(class)
s"
)
related_name
=
"content_type_set_for_
%(class)
s"
)
object_id
=
models
.
PositiveIntegerField
(
_
(
'object ID'
))
object_id
=
models
.
PositiveIntegerField
(
_
(
'object ID'
))
content_object
=
generic
.
GenericForeignKey
(
"content_type"
,
"object_id"
)
content_object
=
generic
.
GenericForeignKey
(
"content_type"
,
"object_id"
)
is_mptt
=
models
.
BooleanField
(
default
=
False
,
editable
=
False
)
is_mptt
=
models
.
BooleanField
(
default
=
False
,
editable
=
False
)
...
@@ -206,6 +208,7 @@ class ArticleForObject(models.Model):
...
@@ -206,6 +208,7 @@ class ArticleForObject(models.Model):
# Do not allow several objects
# Do not allow several objects
unique_together
=
(
'content_type'
,
'object_id'
)
unique_together
=
(
'content_type'
,
'object_id'
)
class
BaseRevisionMixin
(
models
.
Model
):
class
BaseRevisionMixin
(
models
.
Model
):
"""This is an abstract model used as a mixin: Do not override any of the
"""This is an abstract model used as a mixin: Do not override any of the
core model methods but respect the inheritor's freedom to do so itself."""
core model methods but respect the inheritor's freedom to do so itself."""
...
@@ -215,10 +218,10 @@ class BaseRevisionMixin(models.Model):
...
@@ -215,10 +218,10 @@ class BaseRevisionMixin(models.Model):
user_message
=
models
.
TextField
(
blank
=
True
,)
user_message
=
models
.
TextField
(
blank
=
True
,)
automatic_log
=
models
.
TextField
(
blank
=
True
,
editable
=
False
,)
automatic_log
=
models
.
TextField
(
blank
=
True
,
editable
=
False
,)
ip_address
=
models
.
IPAddressField
(
_
(
'IP address'
),
blank
=
True
,
null
=
True
,
editable
=
False
)
ip_address
=
models
.
IPAddressField
(
_
(
'IP address'
),
blank
=
True
,
null
=
True
,
editable
=
False
)
user
=
models
.
ForeignKey
(
compat
.
USER_MODEL
,
verbose_name
=
_
(
'user'
),
user
=
models
.
ForeignKey
(
compat
.
USER_MODEL
,
verbose_name
=
_
(
'user'
),
blank
=
True
,
null
=
True
,
blank
=
True
,
null
=
True
,
on_delete
=
models
.
SET_NULL
)
on_delete
=
models
.
SET_NULL
)
modified
=
models
.
DateTimeField
(
auto_now
=
True
)
modified
=
models
.
DateTimeField
(
auto_now
=
True
)
created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
created
=
models
.
DateTimeField
(
auto_now_add
=
True
)
...
@@ -234,7 +237,7 @@ class BaseRevisionMixin(models.Model):
...
@@ -234,7 +237,7 @@ class BaseRevisionMixin(models.Model):
verbose_name
=
_
(
'deleted'
),
verbose_name
=
_
(
'deleted'
),
default
=
False
,
default
=
False
,
)
)
locked
=
models
.
BooleanField
(
locked
=
models
.
BooleanField
(
verbose_name
=
_
(
'locked'
),
verbose_name
=
_
(
'locked'
),
default
=
False
,
default
=
False
,
)
)
...
@@ -249,7 +252,9 @@ class BaseRevisionMixin(models.Model):
...
@@ -249,7 +252,9 @@ class BaseRevisionMixin(models.Model):
class
Meta
:
class
Meta
:
abstract
=
True
abstract
=
True
@python_2_unicode_compatible
class
ArticleRevision
(
BaseRevisionMixin
,
models
.
Model
):
class
ArticleRevision
(
BaseRevisionMixin
,
models
.
Model
):
"""This is where main revision data is stored. To make it easier to
"""This is where main revision data is stored. To make it easier to
copy, do NEVER create m2m relationships."""
copy, do NEVER create m2m relationships."""
...
@@ -273,7 +278,7 @@ class ArticleRevision(BaseRevisionMixin, models.Model):
...
@@ -273,7 +278,7 @@ class ArticleRevision(BaseRevisionMixin, models.Model):
# help_text=_('If set, the article will redirect to the contents of another article.'),
# help_text=_('If set, the article will redirect to the contents of another article.'),
# related_name='redirect_set')
# related_name='redirect_set')
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
return
"
%
s (
%
d)"
%
(
self
.
title
,
self
.
revision_number
)
return
"
%
s (
%
d)"
%
(
self
.
title
,
self
.
revision_number
)
def
inherit_predecessor
(
self
,
article
):
def
inherit_predecessor
(
self
,
article
):
...
@@ -328,10 +333,12 @@ def _clear_ancestor_cache(article):
...
@@ -328,10 +333,12 @@ def _clear_ancestor_cache(article):
for
ancestor
in
article
.
ancestor_objects
():
for
ancestor
in
article
.
ancestor_objects
():
ancestor
.
article
.
clear_cache
()
ancestor
.
article
.
clear_cache
()
def
on_article_save_clear_cache
(
instance
,
**
kwargs
):
def
on_article_save_clear_cache
(
instance
,
**
kwargs
):
on_article_delete_clear_cache
(
instance
,
**
kwargs
)
on_article_delete_clear_cache
(
instance
,
**
kwargs
)
post_save
.
connect
(
on_article_save_clear_cache
,
Article
)
post_save
.
connect
(
on_article_save_clear_cache
,
Article
)
def
on_article_delete_clear_cache
(
instance
,
**
kwargs
):
def
on_article_delete_clear_cache
(
instance
,
**
kwargs
):
_clear_ancestor_cache
(
instance
)
_clear_ancestor_cache
(
instance
)
instance
.
clear_cache
()
instance
.
clear_cache
()
...
...
wiki/models/pluginbase.py
View file @
e56a78a7
...
@@ -29,6 +29,7 @@ There are three kinds of plugin base models:
...
@@ -29,6 +29,7 @@ There are three kinds of plugin base models:
from
.article
import
ArticleRevision
,
BaseRevisionMixin
from
.article
import
ArticleRevision
,
BaseRevisionMixin
from
wiki.conf
import
settings
from
wiki.conf
import
settings
class
ArticlePlugin
(
models
.
Model
):
class
ArticlePlugin
(
models
.
Model
):
"""This is the mother of all plugins. Extending from it means a deletion
"""This is the mother of all plugins. Extending from it means a deletion
of an article will CASCADE to your plugin, and the database will be kept
of an article will CASCADE to your plugin, and the database will be kept
...
@@ -45,10 +46,13 @@ class ArticlePlugin(models.Model):
...
@@ -45,10 +46,13 @@ class ArticlePlugin(models.Model):
# Permission methods - you should override these, if they don't fit your logic.
# Permission methods - you should override these, if they don't fit your logic.
def
can_read
(
self
,
user
):
def
can_read
(
self
,
user
):
return
self
.
article
.
can_read
(
user
)
return
self
.
article
.
can_read
(
user
)
def
can_write
(
self
,
user
):
def
can_write
(
self
,
user
):
return
self
.
article
.
can_write
(
user
)
return
self
.
article
.
can_write
(
user
)
def
can_delete
(
self
,
user
):
def
can_delete
(
self
,
user
):
return
self
.
article
.
can_delete
(
user
)
return
self
.
article
.
can_delete
(
user
)
def
can_moderate
(
self
,
user
):
def
can_moderate
(
self
,
user
):
return
self
.
article
.
can_moderate
(
user
)
return
self
.
article
.
can_moderate
(
user
)
...
@@ -60,7 +64,8 @@ class ArticlePlugin(models.Model):
...
@@ -60,7 +64,8 @@ class ArticlePlugin(models.Model):
# Override this setting with app_label = '' in your extended model
# Override this setting with app_label = '' in your extended model
# if it lives outside the wiki app.
# if it lives outside the wiki app.
app_label
=
settings
.
APP_LABEL
app_label
=
settings
.
APP_LABEL
class
ReusablePlugin
(
ArticlePlugin
):
class
ReusablePlugin
(
ArticlePlugin
):
"""Extend from this model if you have a plugin that may be related to many
"""Extend from this model if you have a plugin that may be related to many
articles. Please note that the ArticlePlugin.article ForeignKey STAYS! This
articles. Please note that the ArticlePlugin.article ForeignKey STAYS! This
...
@@ -75,9 +80,9 @@ class ReusablePlugin(ArticlePlugin):
...
@@ -75,9 +80,9 @@ class ReusablePlugin(ArticlePlugin):
"""
"""
# The article on which the plugin was originally created.
# The article on which the plugin was originally created.
# Used to apply permissions.
# Used to apply permissions.
ArticlePlugin
.
article
.
on_delete
=
models
.
SET_NULL
ArticlePlugin
.
article
.
on_delete
=
models
.
SET_NULL
ArticlePlugin
.
article
.
verbose_name
=
_
(
'original article'
)
ArticlePlugin
.
article
.
verbose_name
=
_
(
'original article'
)
ArticlePlugin
.
article
.
help_text
=
_
(
'Permissions are inherited from this article'
)
ArticlePlugin
.
article
.
help_text
=
_
(
'Permissions are inherited from this article'
)
ArticlePlugin
.
article
.
null
=
True
ArticlePlugin
.
article
.
null
=
True
ArticlePlugin
.
article
.
blank
=
True
ArticlePlugin
.
article
.
blank
=
True
...
@@ -87,10 +92,13 @@ class ReusablePlugin(ArticlePlugin):
...
@@ -87,10 +92,13 @@ class ReusablePlugin(ArticlePlugin):
# before handling permissions....
# before handling permissions....
def
can_read
(
self
,
user
):
def
can_read
(
self
,
user
):
return
self
.
article
.
can_read
(
user
)
if
self
.
article
else
False
return
self
.
article
.
can_read
(
user
)
if
self
.
article
else
False
def
can_write
(
self
,
user
):
def
can_write
(
self
,
user
):
return
self
.
article
.
can_write
(
user
)
if
self
.
article
else
False
return
self
.
article
.
can_write
(
user
)
if
self
.
article
else
False
def
can_delete
(
self
,
user
):
def
can_delete
(
self
,
user
):
return
self
.
article
.
can_delete
(
user
)
if
self
.
article
else
False
return
self
.
article
.
can_delete
(
user
)
if
self
.
article
else
False
def
can_moderate
(
self
,
user
):
def
can_moderate
(
self
,
user
):
return
self
.
article
.
can_moderate
(
user
)
if
self
.
article
else
False
return
self
.
article
.
can_moderate
(
user
)
if
self
.
article
else
False
...
@@ -109,8 +117,10 @@ class ReusablePlugin(ArticlePlugin):
...
@@ -109,8 +117,10 @@ class ReusablePlugin(ArticlePlugin):
# if it lives outside the wiki app.
# if it lives outside the wiki app.
app_label
=
settings
.
APP_LABEL
app_label
=
settings
.
APP_LABEL
class
SimplePluginCreateError
(
Exception
):
pass
class
SimplePluginCreateError
(
Exception
):
pass
class
SimplePlugin
(
ArticlePlugin
):
class
SimplePlugin
(
ArticlePlugin
):
"""
"""
Inherit from this model and make sure to specify an article when
Inherit from this model and make sure to specify an article when
...
@@ -162,6 +172,7 @@ class SimplePlugin(ArticlePlugin):
...
@@ -162,6 +172,7 @@ class SimplePlugin(ArticlePlugin):
# if it lives outside the wiki app.
# if it lives outside the wiki app.
app_label
=
settings
.
APP_LABEL
app_label
=
settings
.
APP_LABEL
class
RevisionPlugin
(
ArticlePlugin
):
class
RevisionPlugin
(
ArticlePlugin
):
"""
"""
If you want your plugin to maintain revisions, extend from this one,
If you want your plugin to maintain revisions, extend from this one,
...
@@ -253,6 +264,7 @@ class RevisionPluginRevision(BaseRevisionMixin, models.Model):
...
@@ -253,6 +264,7 @@ class RevisionPluginRevision(BaseRevisionMixin, models.Model):
# It's my art, when I disguise my body in the shape of a plane.
# It's my art, when I disguise my body in the shape of a plane.
# (Shellac, 1993)
# (Shellac, 1993)
def
update_simple_plugins
(
**
kwargs
):
def
update_simple_plugins
(
**
kwargs
):
"""Every time a new article revision is created, we update all active
"""Every time a new article revision is created, we update all active
plugins to match this article revision"""
plugins to match this article revision"""
...
@@ -262,15 +274,18 @@ def update_simple_plugins(**kwargs):
...
@@ -262,15 +274,18 @@ def update_simple_plugins(**kwargs):
# TODO: This was breaking things. SimplePlugin doesn't have a revision?
# TODO: This was breaking things. SimplePlugin doesn't have a revision?
p_revisions
.
update
(
article_revision
=
instance
)
p_revisions
.
update
(
article_revision
=
instance
)
def
on_article_plugin_post_save
(
**
kwargs
):
def
on_article_plugin_post_save
(
**
kwargs
):
articleplugin
=
kwargs
[
'instance'
]
articleplugin
=
kwargs
[
'instance'
]
articleplugin
.
article
.
clear_cache
()
articleplugin
.
article
.
clear_cache
()
def
on_reusable_plugin_post_save
(
**
kwargs
):
def
on_reusable_plugin_post_save
(
**
kwargs
):
reusableplugin
=
kwargs
[
'instance'
]
reusableplugin
=
kwargs
[
'instance'
]
for
article
in
reusableplugin
.
articles
.
all
():
for
article
in
reusableplugin
.
articles
.
all
():
article
.
clear_cache
()
article
.
clear_cache
()
def
on_revision_plugin_revision_post_save
(
**
kwargs
):
def
on_revision_plugin_revision_post_save
(
**
kwargs
):
revision
=
kwargs
[
'instance'
]
revision
=
kwargs
[
'instance'
]
revision
.
plugin
.
article
.
clear_cache
()
revision
.
plugin
.
article
.
clear_cache
()
...
...
wiki/models/urlpath.py
View file @
e56a78a7
...
@@ -14,6 +14,8 @@ from django.db import models, transaction
...
@@ -14,6 +14,8 @@ from django.db import models, transaction
from
six.moves
import
filter
from
six.moves
import
filter
#Django 1.6 transaction API, required for 1.8+
#Django 1.6 transaction API, required for 1.8+
from
django.utils.encoding
import
python_2_unicode_compatible
try
:
try
:
notrans
=
transaction
.
non_atomic_requests
notrans
=
transaction
.
non_atomic_requests
except
:
except
:
...
@@ -33,6 +35,8 @@ from wiki.models.article import ArticleRevision, ArticleForObject, Article
...
@@ -33,6 +35,8 @@ from wiki.models.article import ArticleRevision, ArticleForObject, Article
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
@python_2_unicode_compatible
class
URLPath
(
MPTTModel
):
class
URLPath
(
MPTTModel
):
"""
"""
Strategy: Very few fields go here, as most has to be managed through an
Strategy: Very few fields go here, as most has to be managed through an
...
@@ -155,7 +159,7 @@ class URLPath(MPTTModel):
...
@@ -155,7 +159,7 @@ class URLPath(MPTTModel):
class
MPTTMeta
:
class
MPTTMeta
:
pass
pass
def
__
unicode
__
(
self
):
def
__
str
__
(
self
):
path
=
self
.
path
path
=
self
.
path
return
path
if
path
else
ugettext
(
"(root)"
)
return
path
if
path
else
ugettext
(
"(root)"
)
...
@@ -260,6 +264,7 @@ class URLPath(MPTTModel):
...
@@ -260,6 +264,7 @@ class URLPath(MPTTModel):
# Just get this once
# Just get this once
urlpath_content_type
=
None
urlpath_content_type
=
None
def
on_article_relation_save
(
**
kwargs
):
def
on_article_relation_save
(
**
kwargs
):
global
urlpath_content_type
global
urlpath_content_type
instance
=
kwargs
[
'instance'
]
instance
=
kwargs
[
'instance'
]
...
@@ -270,12 +275,14 @@ def on_article_relation_save(**kwargs):
...
@@ -270,12 +275,14 @@ def on_article_relation_save(**kwargs):
post_save
.
connect
(
on_article_relation_save
,
ArticleForObject
)
post_save
.
connect
(
on_article_relation_save
,
ArticleForObject
)
class
Namespace
:
class
Namespace
:
# An instance of Namespace simulates "nonlocal variable_name" declaration
# An instance of Namespace simulates "nonlocal variable_name" declaration
# in any nested function, that is possible in Python 3. It allows assigning
# in any nested function, that is possible in Python 3. It allows assigning
# to non local variable without rebinding it local. See PEP 3104.
# to non local variable without rebinding it local. See PEP 3104.
pass
pass
def
on_article_delete
(
instance
,
*
args
,
**
kwargs
):
def
on_article_delete
(
instance
,
*
args
,
**
kwargs
):
# If an article is deleted, then throw out its URLPaths
# If an article is deleted, then throw out its URLPaths
# But move all descendants to a lost-and-found node.
# But move all descendants to a lost-and-found node.
...
@@ -286,18 +293,19 @@ def on_article_delete(instance, *args, **kwargs):
...
@@ -286,18 +293,19 @@ def on_article_delete(instance, *args, **kwargs):
# that the lost-and-found article can be deleted without being recreated!
# that the lost-and-found article can be deleted without being recreated!
ns
=
Namespace
()
# nonlocal namespace backported to Python 2.x
ns
=
Namespace
()
# nonlocal namespace backported to Python 2.x
ns
.
lost_and_found
=
None
ns
.
lost_and_found
=
None
def
get_lost_and_found
():
def
get_lost_and_found
():
if
ns
.
lost_and_found
:
if
ns
.
lost_and_found
:
return
ns
.
lost_and_found
return
ns
.
lost_and_found
try
:
try
:
ns
.
lost_and_found
=
URLPath
.
objects
.
get
(
slug
=
settings
.
LOST_AND_FOUND_SLUG
,
ns
.
lost_and_found
=
URLPath
.
objects
.
get
(
slug
=
settings
.
LOST_AND_FOUND_SLUG
,
parent
=
URLPath
.
root
(),
parent
=
URLPath
.
root
(),
site
=
site
)
site
=
site
)
except
URLPath
.
DoesNotExist
:
except
URLPath
.
DoesNotExist
:
article
=
Article
(
group_read
=
True
,
article
=
Article
(
group_read
=
True
,
group_write
=
False
,
group_write
=
False
,
other_read
=
False
,
other_read
=
False
,
other_write
=
False
)
other_write
=
False
)
article
.
add_revision
(
ArticleRevision
(
article
.
add_revision
(
ArticleRevision
(
content
=
_
(
'Articles who lost their parents
\n
'
content
=
_
(
'Articles who lost their parents
\n
'
'===============================
\n\n
'
'===============================
\n\n
'
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment