Commit 2eae064d by benjaoming

Correcting errors caused by removal of Article.title field. Almost done with Delete view.

parent c3303e15
......@@ -51,12 +51,19 @@ def get_article(func=None, can_read=True, can_write=False):
pathlist = filter(lambda x: x!="", path.split("/"),)
path = "/".join(pathlist[:-1])
parent = models.URLPath.get_by_path(path)
return redirect(reverse("wiki:create_url", args=(parent.path,)) + "?slug=%s" % pathlist[-1])
return redirect(reverse("wiki:create", kwargs={'path': parent.path,}) + "?slug=%s" % pathlist[-1])
except models.URLPath.DoesNotExist:
# TODO: Make a nice page
return HttpResponseNotFound("This article was not found, and neither was the parent. This page should look nicer.")
# TODO: If the article is not found but it exists, there is a permission error!
article = get_object_or_404(articles, id=urlpath.article.id)
if urlpath.article:
article = get_object_or_404(articles, id=urlpath.article.id)
else:
# Somehow article is gone
return_url = reverse('wiki:get', kwargs={'path': urlpath.parent.path})
urlpath.delete()
return return_url
kwargs['urlpath'] = urlpath
......
......@@ -13,7 +13,7 @@ from wiki.editors import editor
from wiki.core.diff import simple_merge
from django.forms.widgets import HiddenInput
class CreateRoot(forms.Form):
class CreateRootForm(forms.Form):
title = forms.CharField(label=_(u'Title'), help_text=_(u'Initial title of the article. May be overridden with revision titles.'))
content = forms.CharField(label=_(u'Type in some contents'),
......@@ -175,7 +175,7 @@ class CreateForm(forms.Form):
self.urlpath_parent = urlpath_parent
title = forms.CharField(label=_(u'Title'),)
slug = forms.SlugField(label=_(u'Slug'), help_text=_(u"This will be the address where your article can be found. Use only alphanumeric characters and '-' or '_'."),)
slug = forms.SlugField(label=_(u'Slug'), help_text=_(u"This will be the address where your article can be found. Use only alphanumeric characters and - or _. Note that you cannot change the slug after creating the article."),)
content = forms.CharField(label=_(u'Contents'),
required=False, widget=editor.get_widget()) #@UndefinedVariable
......@@ -186,8 +186,14 @@ class CreateForm(forms.Form):
slug = self.cleaned_data['slug']
if slug[0] == "_":
raise forms.ValidationError(_(u'A slug may not begin with an underscore.'))
if models.URLPath.objects.filter(slug=slug, parent=self.urlpath_parent):
raise forms.ValidationError(_(u'A slug named "%s" already exists.') % slug)
already_existing_slug = models.URLPath.objects.filter(slug=slug, parent=self.urlpath_parent)
if already_existing_slug:
slug = already_existing_slug[0]
if slug.deleted:
raise forms.ValidationError(_(u'A deleted article with slug "%s" already exists.') % slug)
else:
raise forms.ValidationError(_(u'A slug named "%s" already exists.') % slug)
return slug
class PermissionsForm(forms.ModelForm):
......@@ -224,10 +230,23 @@ class PermissionsForm(forms.ModelForm):
class DeleteForm(forms.Form):
confirm = forms.BooleanField(required=False)
purge = forms.BooleanField(widget=HiddenInput(), required=False)
def __init__(self, *args, **kwargs):
self.article = kwargs.pop('article')
self.children = kwargs.pop('children')
super(DeleteForm, self).__init__(*args, **kwargs)
confirm = forms.BooleanField(required=False,
label=_(u'Confirm'))
purge = forms.BooleanField(widget=HiddenInput(), required=False,
label=_(u'Purge'),
help_text=_(u'Purge the article: Completely remove it (and all its contents) with no undo.'))
revision = forms.ModelChoiceField(models.ArticleRevision.objects.all(),
widget=HiddenInput(), required=False)
def clean(self):
cd = self.cleaned_data
if not cd['confirm']:
raise forms.ValidationError(_(u'You are not sure enough!'))
if cd['revision'] != self.article.current_revision:
raise forms.ValidationError(_(u'While you tried to delete this article, it was modified. TAKE CARE!'))
return cd
\ No newline at end of file
......@@ -110,7 +110,7 @@ class URLPath(MPTTModel):
if not root_nodes:
# (get_or_create does not work for MPTT models??)
root = cls.objects.create(site=site)
article = Article(title=title)
article = Article()
article.add_revision(ArticleRevision(title=title, **kwargs),
save=True)
article.add_object_relation(root)
......@@ -122,7 +122,7 @@ class URLPath(MPTTModel):
def create_article(cls, parent, slug, site=None, title="Root", **kwargs):
if not site: site = Site.objects.get_current()
newpath = cls.objects.create(site=site, parent=parent, slug=slug)
article = Article(title=title)
article = Article()
article.add_revision(ArticleRevision(title=title, **kwargs),
save=True)
article.add_object_relation(newpath)
......@@ -153,16 +153,16 @@ def on_article_delete(instance, *args, **kwargs):
lost_and_found = URLPath.objects.create(slug=settings.LOST_AND_FOUND_SLUG,
parent=URLPath.root(),
site=site,)
article = Article(title=_(u"Lost and found"),
group_read = True,
article = Article(group_read = True,
group_write = False,
other_read = False,
other_write = False)
article.add_revision(ArticleRevision(
content=_(u'Articles who lost their parents'
'===============================')))
'==============================='),
title=_(u"Lost and found")))
for urlpath in URLPath.objects.filter(articles__article=article, site=site):
for urlpath in URLPath.objects.filter(articles__article=instance, site=site):
for child in urlpath.get_children():
child.move_to(lost_and_found)
......
# Key for django_notify
ARTICLE_EDIT = "article_edit"
ARTICLE_CREATE = "article_create"
......@@ -6,7 +6,7 @@ from django.db.models import signals
from django_notify import notify
from django_notify.models import Subscription
from wiki.plugins.notifications import ARTICLE_CREATE, ARTICLE_EDIT
from wiki.plugins.notifications import ARTICLE_EDIT
from wiki import models as wiki_models
from wiki.core import plugins_registry
......@@ -28,23 +28,19 @@ def default_url(article, urlpath=None):
url = reverse('wiki:get', kwargs={'article_id': article.id})
return url
def post_article_save(instance, **kwargs):
if kwargs.get('created', False):
url = default_url(instance)
notify(_(u'New article created: %s') % instance.title, ARTICLE_CREATE,
target_object=instance, url=url)
def post_article_revision_save(instance, **kwargs):
if kwargs.get('created', False):
url = default_url(instance.article)
notify(_(u'Article modified: %s') % instance.title, ARTICLE_EDIT,
target_object=instance.article, url=url)
# Create notifications when new articles are saved. We do NOT care
# about Article objects that are just modified, because many properties
# are modified without any notifications necessary!
signals.post_save.connect(post_article_save, sender=wiki_models.Article,)
if instance.deleted:
notify(_(u'Article deleted: %s') % instance.title, ARTICLE_EDIT,
target_object=instance.article, url=url)
elif instance.previous_revision:
notify(_(u'Article modified: %s') % instance.title, ARTICLE_EDIT,
target_object=instance.article, url=url)
else:
notify(_(u'New article created: %s') % instance.title, ARTICLE_EDIT,
target_object=instance, url=url)
# Whenever a new revision is created, we notifý users that an article
# was edited
signals.post_save.connect(post_article_revision_save, sender=wiki_models.ArticleRevision,)
......
......@@ -5,22 +5,54 @@
{% block pagetitle %}{% trans "Delete article" %}{% endblock %}
{% block wiki_contents %}
{% include "wiki/includes/editormedia.html" %}
<h1 class="page-header">{% trans "Delete" %} "{{ article.current_revision.title }}"?</h1>
<h1 class="page-header">{% trans "Delete" %} "{{ article.current_revision.title }}"</h1>
<form method="POST" class="form-horizontal">
{% wiki_form create_form %}
<div class="form-actions">
<a href="{% url 'wiki:get' path=parent_urlpath.path %}" class="btn btn-large">
<span class="icon-circle-arrow-left"></span>
{% trans "Go back" %}
</a>
<button type="submit" name="save_changes" class="btn btn-primary btn-large">
<span class="icon-plus"></span>
{% trans "Create article" %}
</button>
</div>
</form>
{% if cannot_delete_root %}
<p class="lead">{% trans "You cannot delete a root article." %}</p>
<p><a href="{% url 'wiki:get' path=urlpath.path article_id=article.id %}">{% trans "Go back" %}</a></p>
{% else %}
{% if cannot_delete_children %}
<p class="alert alert-error"><strong>{% trans "You cannot delete this article because you do not have permission to delete articles with children. Try to remove the children manually one-by-one." %}</strong></p>
{% endif %}
{% if children %}
<p class="lead">{% trans "You are deleting an article. This means that its children will loose their connection to the rest of the tree and moved to Lost and Found. Only do this if you know what you're doing." %}</p>
<h2>{% trans "Articles that will be orphans" %}</h2>
<ul>
{% for child in children %}
<li><a href="{% url 'wiki:get' path=child.article.path %}" target="_blank">{{ child.article }}</a></li>
{% endfor %}
</ul>
{% else %}
<p class="lead">{% trans "You are deleting an article. Please confirm." %}</p>
{% endif %}
{% if not cannot_delete_children %}
<form method="POST" class="form-horizontal">
{% wiki_form delete_form %}
<div class="form-actions">
<a href="{% url 'wiki:get' path=urlpath.path article_id=article.id %}" class="btn btn-large">
<span class="icon-circle-arrow-left"></span>
{% trans "Go back" %}
</a>
<button type="submit" name="save_changes" class="btn btn-critical btn-large">
<span class="icon-plus"></span>
{% trans "Delete article" %}
</button>
</div>
</form>
{% endif %}
{% endif %}
{% endblock %}
......@@ -49,7 +49,7 @@ for plugin in plugins_registry._cache.values():
urlpatterns += patterns('',
# Paths decided by URLs
url('^(?P<path>.+/|)_create/$', article.Create.as_view(), name='create'),
url('^(?P<path>.+/|)_delete/$', article.Edit.as_view(), name='delete'),
url('^(?P<path>.+/|)_delete/$', article.Delete.as_view(), name='delete'),
url('^(?P<path>.+/|)_edit/$', article.Edit.as_view(), name='edit'),
url('^(?P<path>.+/|)_preview/$', 'wiki.views.article.preview', name='preview'),
url('^(?P<path>.+/|)_history/$', article.History.as_view(), name='history'),
......
......@@ -19,6 +19,7 @@ from wiki.decorators import get_article, json_view
from django.core.urlresolvers import reverse
from django.db import transaction
from wiki.core.exceptions import NoRootURL
from django_notify.decorators import disable_notify
class ArticleView(ArticleMixin, TemplateView):
......@@ -106,47 +107,95 @@ class Delete(FormView, ArticleMixin):
@method_decorator(get_article(can_write=True))
def dispatch(self, request, article, *args, **kwargs):
super_return = super(Delete, self).dispatch(request, article, *args, **kwargs)
urlpath = kwargs.get('urlpath', None)
# Where to go after deletion...
self.next = request.GET.get('next', None)
self.cannot_delete_root = False
if not self.next:
if self.urlpath:
self.next = reverse('wiki:get', path=self.urlpath.parent.path)
if urlpath and urlpath.parent:
self.next = reverse('wiki:get', kwargs={'path': urlpath.parent.path})
elif urlpath:
self.cannot_delete_root = True
else:
for art_obj in self.objectforarticle_set.filter(is_mptt=True):
self.next = reverse('wiki:get', kwargs={'article_id': art_obj.parent.article.id})
return super_return
for art_obj in article.articleforobject_set.filter(is_mptt=True):
if art_obj.content_object.parent:
self.next = reverse('wiki:get', kwargs={'article_id': art_obj.content_object.parent.article.id})
else:
self.cannot_delete_root = True
# Fetch children if necessary
self.children = []
if not self.cannot_delete_root:
self.children = article.get_children()
self.cannot_delete_children = False
if self.children and not request.user.has_perm('wiki.moderator'):
self.cannot_delete_children = True
return super(Delete, self).dispatch(request, article, *args, **kwargs)
def get_initial(self):
return {'revision': self.article.current_revision}
def get_form(self, form_class):
form = FormView.get_form(self, form_class)
form = super(Delete, self).get_form(form_class)
if self.request.user.has_perm('wiki.moderator'):
form.fields['purge'].widget = forms.forms.CheckboxInput()
return form
def get_form_kwargs(self):
kwargs = FormView.get_form_kwargs(self)
kwargs['article'] = self.article
kwargs['children'] = self.children
return kwargs
@disable_notify
def delete_children(self, purge=False):
if purge:
for child in self.children:
child.delete()
else:
for child in self.children:
revision = models.ArticleRevision()
revision.inherit_predecessor(child)
revision.deleted = True
child.add_revision(revision)
def form_valid(self, form):
cd = form.cleaned_data
if self.cannot_delete_root or self.cannot_delete_children:
messages.error(self.request, _(u'This article cannot be deleted because it has children or is a root article.'))
return redirect('wiki:get', article_id=self.article.id)
# First, remove children
self.delete_children(purge=cd['purge'])
if self.request.user.has_perm('wiki.moderator') and cd['purge']:
pass
self.article.delete()
messages.success(self.request, _(u'This article together with all its contents are now completely gone! Thanks!'))
else:
revision = models.ArticleRevision()
revision.inherit_predecessor(self.article)
revision.deleted = True
self.article.add_revision(revision)
messages.success(self.request, _(u'This article is now marked as deleted! Thanks for keeping the site free from unwanted material!'))
def get_success_url(self):
return redirect(self.next)
def get_context_data(self, **kwargs):
kwargs['parent_urlpath'] = self.urlpath
kwargs['parent_article'] = self.article
kwargs['create_form'] = kwargs.pop('form', None)
kwargs['editor'] = editors.editor
return super(Create, self).get_context_data(**kwargs)
kwargs['delete_form'] = kwargs.pop('form', None)
kwargs['cannot_delete_root'] = self.cannot_delete_root
children = []
cnt = 0
for child in self.children:
if cnt > 21: break
children.append(child)
kwargs['children'] = children[:20]
kwargs['children_more'] = len(children) > 20
kwargs['cannot_delete_children'] = self.cannot_delete_children
return super(Delete, self).get_context_data(**kwargs)
class Edit(FormView, ArticleMixin):
......@@ -378,6 +427,7 @@ def merge(request, article, revision_id, urlpath=None, template_file="wiki/previ
'content': content})
return render_to_response(template_file, c)
# TODO: Should be a class-based view
def root_create(request):
try:
root = models.URLPath.root()
......@@ -390,13 +440,13 @@ def root_create(request):
if not request.user.has_perm('wiki.add_article'):
return redirect(reverse("wiki:login") + "?next=" + reverse("wiki:root_create"))
if request.method == 'POST':
create_form = forms.CreateRoot(request.POST)
create_form = forms.CreateRootForm(request.POST)
if create_form.is_valid():
models.URLPath.create_root(title=create_form.cleaned_data["title"],
content=create_form.cleaned_data["content"])
return redirect("wiki:root")
else:
create_form = forms.CreateRoot()
create_form = forms.CreateRootForm()
c = RequestContext(request, {'create_form': create_form,
'editor': editors.editor,})
......
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