Merge lp:~widelands-dev/widelands-website/bug-1399461_error_on_renaming_article into lp:widelands-website

Proposed by kaputtnik
Status: Merged
Merged at revision: 447
Proposed branch: lp:~widelands-dev/widelands-website/bug-1399461_error_on_renaming_article
Merge into: lp:widelands-website
Diff against target: 402 lines (+188/-44)
10 files modified
templates/admin/wiki/article/change_form.html (+9/-0)
templates/wiki/backlinks.html (+38/-0)
templates/wiki/edit.html (+4/-4)
templates/wiki/view.html (+9/-0)
wiki/admin.py (+5/-5)
wiki/forms.py (+24/-8)
wiki/migrations/0002_auto_20161218_1056.py (+19/-0)
wiki/models.py (+2/-2)
wiki/urls.py (+3/-0)
wiki/views.py (+75/-25)
To merge this branch: bzr merge lp:~widelands-dev/widelands-website/bug-1399461_error_on_renaming_article
Reviewer Review Type Date Requested Status
SirVer code Approve
Review via email: mp+314033@code.launchpad.net

Commit message

Prevent double names of wiki articles. Add a 'What links here' page.

Description of the change

This fixes bug 1399461 'Renaming an article triggers an error, if article exists' by making the name of an article a unique value on database level. Also prevents reverting an article if the reverting implies renaming and the name to which the article wants to be renamed exists in the meantime. An example (which shows also some other difficulties), imagine some month/years left between the steps:

1. Article "A_1" was created
2. Article "B_1" was created
3. "A_1" get renamed to "A" -> All old links called "A_1" redirects then to article "A"
4. "B_1" get renamed to "A_1" -> All old links called "A_1" open now article "A_1" (not "A" anymore)
5. "A" wants to be reverted to a revision where its name was "A_1" -> This is now prevented, because "A_1" already exists (got renamed from "B_1")

I wanted to prevent step 4 (renaming an article to a name where a redirect exists) but i couldn't fiddle this out. In general i think redirects are not really a good thing at all, because it may lead into many redirects after some time. So i implemented a 'backlinks' page ('What links here'). This page shows following information:

1. All articles which have links to the current name of this article
2. All articles which have links which points to (one of) the old name(s) of this article (redirects)
3. If this article is not linked at all, show a message with a request to link it somewhere

The 2. point has also a request to change the links in all listed articles to point to the current name. Generally speaking: Please remove the redirects
Point 3. has a disadvantage: If an article is only linked over the main menu, it shows also the message to link this article somewhere. Not the best, but i have no idea how to fix this in a convenient manner.

Changes to admin page of wiki:
1. Add a link to show all changesets of this article

If this branch get deployed, one has to run './manage.py migrate' to apply the changes.

To post a comment you must log in.
459. By kaputtnik

removed useless validation error

Revision history for this message
SirVer (sirver) wrote :

> In general i think redirects are not really a good thing at all, because it may lead into many redirects after some time.

While I agree here, they are also sorta required: if some external site links to a site in our Wiki, we want this link to stay valid forever ideally. So we have to track renames (or completely forbid them) and forward to the new page.

About the (internal) redirects: Is it not in our power to fix all internal links that linked to the old page into links that link to the new page? I mean, we can just make a new revision for each page algorithmically that just does the renames. No user interaction is needed.

> If an article is only linked over the main menu, it shows also the message to link this article somewhere.

Could be handled with a custom Django template tag like "WikiLink" that behaves like inter WikiLinking. Not sure if that is really necessary though.

Revision history for this message
kaputtnik (franku) wrote :

> > In general i think redirects are not really a good thing at all, because it
> may lead into many redirects after some time.
>
> While I agree here, they are also sorta required: if some external site links
> to a site in our Wiki, we want this link to stay valid forever ideally. So we
> have to track renames (or completely forbid them) and forward to the new page.

Forbid renaming isn't a good thing also. If one wants to put the content of an article under a new name, he has to create then a new article and copy and paste the content from the old article to the new one. So all changesets are gone and reverting to the previous situation is not possible anymore.

What should we do with following situation? An existing example:

1. https://wl.widelands.org/wiki/Description/
2. https://wl.widelands.org/wiki/GameHelp/

2. is a redirect to 1. But it is currently possible to create a new article GameHelp:

https://wl.widelands.org/wiki/edit/GameHelp/

When saving this new article, all old redirects are gone, respectively all Links to GameHelp open then the new article. Should creating of articles prevented if a redirect exists? On the long run this would mean the available amount of article names shrinks, because some articles reserve two (or more) names.

> About the (internal) redirects: Is it not in our power to fix all internal
> links that linked to the old page into links that link to the new page? I
> mean, we can just make a new revision for each page algorithmically that just
> does the renames. No user interaction is needed.

If we want redirects to stay forever, this isn't needed, isn't it? And reverting to a previous revision put then the old links in again. But we may need such a functionality also for bug 1595294 "Get rid of wikiwordification".

This is all a bit complicated to me... because our redirects are some kind of "soft-redirects": To determine a redirect the code looks just for the requested name in all changesets. If it is found the corresponding article get opened and the String "(redirected from ...)" is shown. There is no real 'redirect-object' and i have trouble to abstract the redirects. I think other wikis handle redirects in another way: If a renaming is done a new article with the old name is created and the content is the redirect with a special syntax. So there are two existing articles (the article it self, and the redirect to it), whereas we have only one.

See e.g.: https://www.mediawiki.org/wiki/Help:Moving_a_page

460. By kaputtnik

removed request for removing redirects

461. By kaputtnik

wording

Revision history for this message
SirVer (sirver) wrote :

> Should creating of articles prevented if a redirect exists?

Yes, I think this is acceptable. We create maybe 10 articles per year, it will be a while till we run out of names, even including redirects.

> If we want redirects to stay forever, this isn't needed, isn't it?

While that is true, it might still be nice to fix all references we have internally to have consistency.

> There is no real 'redirect-object' and i have trouble to abstract the redirects.

One solution would be to have a separate table that holds only the existing redirects. That table is queried first whenever a article is requested and if a match is found, the redirect is evaluated.

Revision history for this message
kaputtnik (franku) wrote :

> > Should creating of articles prevented if a redirect exists?
>
> Yes, I think this is acceptable. We create maybe 10 articles per year, it will
> be a while till we run out of names, even including redirects.

Ok, then i try to prevent it in this branch :-)

>
> > If we want redirects to stay forever, this isn't needed, isn't it?
>
> While that is true, it might still be nice to fix all references we have
> internally to have consistency.

I think this would be better to manage if we have the other bug fixed and we have also a consistent syntax for internal wiki links.

> > There is no real 'redirect-object' and i have trouble to abstract the
> redirects.
>
> One solution would be to have a separate table that holds only the existing
> redirects. That table is queried first whenever a article is requested and if
> a match is found, the redirect is evaluated.

I have to think about it. But i guess this would be also better to do it in another branch, because this one is only to prevent the renaming to a name an existing article, or a redirect, has.

462. By kaputtnik

added check if an artile name is reserved to not break old links

463. By kaputtnik

trying to edit a redirect opens now the actual article; reworked title check for the form

464. By kaputtnik

Added a hint for check on database level

Revision history for this message
kaputtnik (franku) wrote :

Puhh... hopefully i get it now. Giving the example of

1. https://wl.widelands.org/wiki/Description/
2. https://wl.widelands.org/wiki/GameHelp/ #redirect to 1.

- Trying to open /wiki/edit/GameHelp opens now 'Description' for editing.

Trying to change the title is handled as follows:

For existing articles those circumstances are prevented and a message is shown in the form:
- If the title is in a changeset (so redirects and old links will not break)
- If the title already exists as normal article (handled in wiki/forms.py)

For new articles:
- If one opens /wiki/edit/foo and immediately wants to rename it to 'bar' without saving first, the previous checks are also done. There is one difference: If 'bar' exists as normal article, django checks this on database level, a message is then also shown in the form.

I think this is ready but want to make a last test in the next days. A question:
I am unsure about a nested 'try: ... except:' clause. Is this good coding practice? See:

http://bazaar.launchpad.net/~widelands-dev/widelands-website/bug-1399461_error_on_renaming_article/view/head:/wiki/views.py#L262

Revision history for this message
SirVer (sirver) wrote :

Solution sounds good to me, but I did not test it.

> I am unsure about a nested 'try: ... except:' clause. Is this good coding practice? See:

Yes, that seems fine. I would not know how to code this in another fashion.

Revision history for this message
SirVer (sirver) :
review: Approve (code)
465. By kaputtnik

small fix in html file

Revision history for this message
kaputtnik (franku) wrote :

Thanks for the review :-)

Let's wait for Gun if she complains against my english pronouncing :-)

466. By kaputtnik

reworked the check for emmidiately changing the title for new articles, again

467. By kaputtnik

use our default color for errormessages

Revision history for this message
kaputtnik (franku) wrote :

Found a failure... tomorrow i want to merge this on the alpha site, so anybody can take a look at it and test.

Revision history for this message
kaputtnik (franku) wrote :

Merged but not committed on alpha, migrated the changes related to the database over there. For testing one has to start the alpha site.

Revision history for this message
SirVer (sirver) wrote :

I am unsure about the last comment. Is that a request for testing help? If so, I'd suggest you lanuch and leave the alpha site running.

Revision history for this message
kaputtnik (franku) wrote :

I have interpreted the statement:

> ... , but did not test it

as you would like to test. I think on the alpha site this is easier. The alpha site is running now.

Maybe i have one thing of the changes to explain further: To show the Changesets for an Article one has to open an article in the admin page and on the top right there is now a link called "Changesets".

Once you told me the alpha site should not run for a longer time, so i shut it down every time i had finished my tests. May we could clarify this on IRC?

Revision history for this message
GunChleoc (gunchleoc) wrote :

Linguistic proofreading done.

468. By kaputtnik

wording

Revision history for this message
kaputtnik (franku) wrote :

Thanks a lot :-)

469. By kaputtnik

reactivated preview

Revision history for this message
kaputtnik (franku) wrote :

This is merged and deployed now on the productive website.

Alpha is offline again.

Revision history for this message
SirVer (sirver) wrote :

Sorry for holding this off :(. I wanted to test this indeed, but I did not get around to it.

> Once you told me the alpha site should not run for a longer time, so i shut it down every time i had finished my tests. May we could clarify this on IRC?

As long as necessary, as short as possible. If it is online for a significant percentage of the year, it will be found by search engines leading to confusing (and mostly insignificant) links in search results. Search is our main influx of users, so this would be suboptimal. A few days at a time if there is something to test is probably not hurting us though. That was my entire thought process.

Revision history for this message
kaputtnik (franku) wrote :

> Sorry for holding this off :(

Sorry that i am such impatient in this case... but i think this branch does not hurt if it is productive. There are no writes to Database or to the storage, so the worst thing that could happen is a not catched server error (we had for a long time nor such errors :-D ). I just wanted to close this thing and work on stuff where this branch would be a help for.

Thanks for the clarification related to alpha :-)

I have seen that you are ill and hopefully you get well soon...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'templates/admin'
=== added directory 'templates/admin/wiki'
=== added directory 'templates/admin/wiki/article'
=== added file 'templates/admin/wiki/article/change_form.html'
--- templates/admin/wiki/article/change_form.html 1970-01-01 00:00:00 +0000
+++ templates/admin/wiki/article/change_form.html 2017-01-18 20:19:31 +0000
@@ -0,0 +1,9 @@
1{% extends "admin/change_form.html" %}
2{% load i18n admin_urls %}
3
4{% block object-tools-items %}
5 <li>
6 <a href="/admin/wiki/changeset/?article__title={{ original.title }}" class="historylink">{% trans "Changesets" %}</a>
7 </li>
8 {% if has_absolute_url %}<li><a href="{{ absolute_url }}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif %}
9{% endblock %}
010
=== added file 'templates/wiki/backlinks.html'
--- templates/wiki/backlinks.html 1970-01-01 00:00:00 +0000
+++ templates/wiki/backlinks.html 2017-01-18 20:19:31 +0000
@@ -0,0 +1,38 @@
1{% extends 'wiki/base.html' %}
2{% load wiki_extras %}
3{% load i18n %}
4{% block title %}
5{{ name }} - Backlinks - {{block.super}}
6{% endblock %}
7
8{% block content %}
9<div class="posRight small">
10 <a class="invertedColor" href="{% url 'wiki_article' name %}">Back to article</a>
11</div>
12<h1>{% trans "Backlinks of " %} {{ name }}</h1>
13<div class="blogEntry">
14 {% if found_links or found_old_links %}
15 {% if found_links %}
16 <h3>The following pages have link(s) which point to this article:</h3>
17 <ul>
18 {% for article in found_links %}
19 <li><a href="{% url 'wiki_article' article.title %}">{{ article.title }}</a></li>
20 {% endfor %}
21 </ul>
22 {% endif %}
23 {% if found_old_links %}
24 <h3>The following articles have links which point to one of the old name(s) of this article (redirects):</h3>
25 <ul>
26 {% for article in found_old_links %}
27 <li><a href="{% url 'wiki_article' article.title %}">{{ article.title }}</a>
28 (has at least one link to: "{{ article.old_title }}")</li>
29 {% endfor %}
30 </ul>
31 {% endif %}
32 {% else %}
33 <p><span class="errormessage">Every Wikipage must be linked from at least one another page.</span>
34 Please link it <img src="/wlmedia/img/smileys/face-smile.png" alt="face-smile.png"> See <a href="/wiki/WikiSyntax/#links">Wiki Syntax</a> for help.</p></p>
35 {% endif %}
36</div>
37{% endblock %}
38
039
=== modified file 'templates/wiki/edit.html'
--- templates/wiki/edit.html 2016-11-26 20:55:21 +0000
+++ templates/wiki/edit.html 2017-01-18 20:19:31 +0000
@@ -60,17 +60,17 @@
60 <!-- Title -->60 <!-- Title -->
61 <tr>61 <tr>
62 <th><label for="id_title">{% trans "Title" %}:</label></th>62 <th><label for="id_title">{% trans "Title" %}:</label></th>
63 <td>{{ form.title.errors }}{{ form.title }}</td>63 <td class="errormessage">{{ form.title.errors }}{{ form.title }}</td>
64 </tr>64 </tr>
65 <!-- Content -->65 <!-- Content -->
66 <tr><th colspan="2"><label for="id_content">{% trans "Content" %}:</label></th></tr>66 <tr><th colspan="2"><label for="id_content">{% trans "Content" %}:</label></th></tr>
67 <tr><td colspan="2" >{{ form.content.errors }}{{ form.content }}</td></tr>67 <tr><td colspan="2" class="errormessage">{{ form.content.errors }}{{ form.content }}</td></tr>
68 <!-- Summary -->68 <!-- Summary -->
69 <tr><th colspan="2"><label for="id_summary">{% trans "Page Summary" %}:</label></th></tr>69 <tr><th colspan="2"><label for="id_summary">{% trans "Page Summary" %}:</label></th></tr>
70 <tr><td colspan="2" >{{ form.summary.errors }}{{ form.summary }}</td></tr>70 <tr><td colspan="2" class="errormessage">{{ form.summary.errors }}{{ form.summary }}</td></tr>
71 <!-- Comment -->71 <!-- Comment -->
72 <tr><th colspan=2><label for="id_comment">{% trans "Comment for this revision" %}:</label></th></tr>72 <tr><th colspan=2><label for="id_comment">{% trans "Comment for this revision" %}:</label></th></tr>
73 <tr><td colspan=2 >{{ form.comment.errors }}{{ form.comment }}</td></tr>73 <tr><td colspan=2 class="errormessage">{{ form.comment.errors }}{{ form.comment }}</td></tr>
74 </table>74 </table>
75 <!-- Markup as hidden element -->75 <!-- Markup as hidden element -->
76 <input type="hidden" name="markup" value="mrk" />76 <input type="hidden" name="markup" value="mrk" />
7777
=== modified file 'templates/wiki/view.html'
--- templates/wiki/view.html 2016-04-26 16:10:04 +0000
+++ templates/wiki/view.html 2017-01-18 20:19:31 +0000
@@ -18,6 +18,8 @@
18 <a class="invertedColor" href="{% url 'wiki_edit' article.title %}">{% trans "Edit this article" %}</a>18 <a class="invertedColor" href="{% url 'wiki_edit' article.title %}">{% trans "Edit this article" %}</a>
19 |19 |
20 <a class="invertedColor" href="{% url 'wiki_article_history' article.title %}">{% trans "Editing history" %}</a>20 <a class="invertedColor" href="{% url 'wiki_article_history' article.title %}">{% trans "Editing history" %}</a>
21 |
22 <a class="invertedColor" href="{% url 'backlinks' article.title %}">{% trans "Backlinks" %}</a>
21 {% if can_observe %}23 {% if can_observe %}
22 | 24 |
23 {% if is_observing %} 25 {% if is_observing %}
@@ -29,6 +31,13 @@
29 {% endif %}31 {% endif %}
30</div>32</div>
31<h1>{{ article.title }}</h1>33<h1>{{ article.title }}</h1>
34
35 {% if messages %}
36 {% for message in messages %}
37 <p class="errormessage">{{ message }}</p>
38 {% endfor %}
39 {% endif %}
40
32<div class="blogEntry">41<div class="blogEntry">
33 {% if not article.id %}42 {% if not article.id %}
34 <p>43 <p>
3544
=== modified file 'wiki/admin.py'
--- wiki/admin.py 2016-11-22 22:17:23 +0000
+++ wiki/admin.py 2017-01-18 20:19:31 +0000
@@ -15,7 +15,7 @@
1515
16class ArticleAdmin(admin.ModelAdmin):16class ArticleAdmin(admin.ModelAdmin):
17 search_fields = ['title']17 search_fields = ['title']
18 list_display = ('title', 'markup', 'created_at', 'last_update',)18 list_display = ('title', 'creator', 'last_update',)
19 list_filter = ('title',)19 list_filter = ('title',)
20 ordering = ['-last_update']20 ordering = ['-last_update']
21 fieldsets = (21 fieldsets = (
@@ -32,11 +32,11 @@
3232
3333
34class ChangeSetAdmin(admin.ModelAdmin):34class ChangeSetAdmin(admin.ModelAdmin):
35 search_fields = ['article__title']35 search_fields = ['old_title']
36 list_display = ('article', 'revision', 'old_title', 'old_markup',36 list_display = ('article', 'old_title', 'old_markup',
37 'editor', 'editor_ip', 'reverted', 'modified',37 'editor', 'reverted', 'modified',
38 'comment')38 'comment')
39 list_filter = ('old_title', 'content_diff')39 list_filter = ('article__title',)
40 ordering = ('-modified',)40 ordering = ('-modified',)
41 fieldsets = (41 fieldsets = (
42 ('Article', {'fields': ('article',)}),42 ('Article', {'fields': ('article',)}),
4343
=== modified file 'wiki/forms.py'
--- wiki/forms.py 2016-12-13 18:28:51 +0000
+++ wiki/forms.py 2017-01-18 20:19:31 +0000
@@ -2,11 +2,11 @@
2import re2import re
33
4from django import forms4from django import forms
5from django.forms import widgets
6from django.contrib.contenttypes.models import ContentType5from django.contrib.contenttypes.models import ContentType
7from django.utils.translation import ugettext_lazy as _6from django.utils.translation import ugettext_lazy as _
87
9from wiki.models import Article8from wiki.models import Article
9from wiki.models import ChangeSet
10from wiki.templatetags.wiki_extras import WIKI_WORD_RE10from wiki.templatetags.wiki_extras import WIKI_WORD_RE
1111
12wikiword_pattern = re.compile('^' + WIKI_WORD_RE + '$')12wikiword_pattern = re.compile('^' + WIKI_WORD_RE + '$')
@@ -34,11 +34,31 @@
34 'group', 'created_at', 'last_update')34 'group', 'created_at', 'last_update')
3535
36 def clean_title(self):36 def clean_title(self):
37 """Page title must be a WikiWord."""37 """Check for some errors regarding the title:
38
39 1. Check for bad characters
40 2. Check for already used titles
41
42 Immediately trying to change the title of a new article to an existing title
43 is handled on the database level.
44
45 """
46
38 title = self.cleaned_data['title']47 title = self.cleaned_data['title']
39 if not wikiword_pattern.match(title):48 if not wikiword_pattern.match(title):
40 raise forms.ValidationError(_('Must be a WikiWord.'))49 raise forms.ValidationError(
4150 _('Only alphanumeric characters, blank spaces and the underscore are allowed in a title.'))
51
52 # 'self.initial' contains the prefilled values of the form
53 pre_title = self.initial.get('title', None)
54 if pre_title != title or not pre_title:
55 # Check if the new name has been used already
56 cs = ChangeSet.objects.filter(old_title=title)
57 if cs:
58 raise forms.ValidationError(
59 _('The title %(title)s is already in use, maybe an other article used to have this name.'), params={'title': title},)
60
61 # title not changed, no errors
42 return title62 return title
4363
44 def clean(self):64 def clean(self):
@@ -52,10 +72,6 @@
52 kw['object_id'] = self.cleaned_data['object_id']72 kw['object_id'] = self.cleaned_data['object_id']
53 except KeyError:73 except KeyError:
54 pass # some error in this fields74 pass # some error in this fields
55 else:
56 if Article.objects.filter(**kw).count():
57 raise forms.ValidationError(
58 _('An article with this title already exists.'))
5975
60 return self.cleaned_data76 return self.cleaned_data
6177
6278
=== added file 'wiki/migrations/0002_auto_20161218_1056.py'
--- wiki/migrations/0002_auto_20161218_1056.py 1970-01-01 00:00:00 +0000
+++ wiki/migrations/0002_auto_20161218_1056.py 2017-01-18 20:19:31 +0000
@@ -0,0 +1,19 @@
1# -*- coding: utf-8 -*-
2from __future__ import unicode_literals
3
4from django.db import models, migrations
5
6
7class Migration(migrations.Migration):
8
9 dependencies = [
10 ('wiki', '0001_initial'),
11 ]
12
13 operations = [
14 migrations.AlterField(
15 model_name='article',
16 name='title',
17 field=models.CharField(unique=True, max_length=50, verbose_name='Title'),
18 ),
19 ]
020
=== modified file 'wiki/models.py'
--- wiki/models.py 2016-12-13 18:28:51 +0000
+++ wiki/models.py 2017-01-18 20:19:31 +0000
@@ -48,8 +48,8 @@
4848
4949
50class Article(models.Model):50class Article(models.Model):
51 """A wiki page."""51 """A wiki page reflecting the actual revision."""
52 title = models.CharField(_(u"Title"), max_length=50)52 title = models.CharField(_(u"Title"), max_length=50, unique=True)
53 content = models.TextField(_(u"Content"))53 content = models.TextField(_(u"Content"))
54 summary = models.CharField(_(u"Summary"), max_length=150,54 summary = models.CharField(_(u"Summary"), max_length=150,
55 null=True, blank=True)55 null=True, blank=True)
5656
=== modified file 'wiki/urls.py'
--- wiki/urls.py 2016-12-13 18:28:51 +0000
+++ wiki/urls.py 2017-01-18 20:19:31 +0000
@@ -56,4 +56,7 @@
5656
57 url(r'^history/(?P<title>' + WIKI_URL_RE + r')/revert/$', views.revert_to_revision,57 url(r'^history/(?P<title>' + WIKI_URL_RE + r')/revert/$', views.revert_to_revision,
58 name='wiki_revert_to_revision'),58 name='wiki_revert_to_revision'),
59
60 url(r'^backlinks/(?P<title>' + WIKI_URL_RE + r')/$', views.backlinks,
61 name='backlinks'),
59]62]
6063
=== modified file 'wiki/views.py'
--- wiki/views.py 2016-12-13 18:28:51 +0000
+++ wiki/views.py 2017-01-18 20:19:31 +0000
@@ -10,7 +10,7 @@
10 HttpResponseNotAllowed, HttpResponse, HttpResponseForbidden)10 HttpResponseNotAllowed, HttpResponse, HttpResponseForbidden)
11from django.shortcuts import get_object_or_404, render_to_response, redirect11from django.shortcuts import get_object_or_404, render_to_response, redirect
12from django.contrib.contenttypes.models import ContentType12from django.contrib.contenttypes.models import ContentType
1313from django.contrib import messages
14from wiki.forms import ArticleForm14from wiki.forms import ArticleForm
15from wiki.models import Article, ChangeSet, dmp15from wiki.models import Article, ChangeSet, dmp
1616
@@ -19,6 +19,7 @@
19from mainpage.templatetags.wl_markdown import do_wl_markdown19from mainpage.templatetags.wl_markdown import do_wl_markdown
2020
21from wl_utils import get_real_ip21from wl_utils import get_real_ip
22import re
2223
23# Settings24# Settings
24# lock duration in minutes25# lock duration in minutes
@@ -260,29 +261,26 @@
260 return HttpResponseForbidden()261 return HttpResponseForbidden()
261262
262 try:263 try:
264 # Try to fetch an existing article
263 article = article_qs.get(**article_args)265 article = article_qs.get(**article_args)
264 except ArticleClass.DoesNotExist:266 except ArticleClass.DoesNotExist:
265 article = None267 # No article found, maybe we have a redirect
268 try:
269 cs = ChangeSet.objects.filter(old_title=title)[0]
270 article = article_qs.get(title=cs.article)
271 except IndexError:
272 # No Article found and no redirect found
273 article = None
266274
267 if request.method == 'POST':275 if request.method == 'POST':
268276
269 form = ArticleFormClass(request.POST, instance=article)277 form = ArticleFormClass(request.POST, instance=article)
270278
271 form.cache_old_content()279 form.cache_old_content()
272 if form.is_valid():280 if form.is_valid():
273281
274 # NOCOMM Franku: This has never worked as i know and is IMHO
275 # useless. This code works with django 1.8 but misses some code
276 # in template. See
277 # https://docs.djangoproject.com/en/1.8/ref/contrib/messages/#module-django.contrib.messages
278
279 if request.user.is_authenticated():282 if request.user.is_authenticated():
280 form.editor = request.user283 form.editor = request.user
281 # if article is None:
282 # user_message = u"Your article was created successfully."
283 # else:
284 # user_message = u"Your article was edited successfully."
285 # messages.success(request, user_message)
286284
287 if ((article is None) and (group_slug is not None)):285 if ((article is None) and (group_slug is not None)):
288 form.group = group286 form.group = group
@@ -478,18 +476,23 @@
478476
479 article = get_object_or_404(article_qs, **article_args)477 article = get_object_or_404(article_qs, **article_args)
480478
481 if request.user.is_authenticated():479
482 article.revert_to(revision, get_real_ip(request), request.user)480 # Check whether there is another Article with the same name to which this article
483 else:481 # wants to be reverted to. If so: prevent it and show a message.
484 article.revert_to(revision, get_real_ip(request))482 old_title = article.changeset_set.filter(
485483 revision=revision+1).get().old_title
486 # NOCOMM Franku: This has never worked as i know and is IMHO484 try:
487 # useless. If we want this it has to be fixed for django 1.8485 art = Article.objects.exclude(pk=article.pk).get(title=old_title)
488 # See comment in edit_article()486 except Article.DoesNotExist:
489 # if request.user.is_authenticated():487 # No existing article found -> reverting possible
490 # request.user.message_set.create(488 if request.user.is_authenticated():
491 # message=u"The article was reverted successfully.")489 article.revert_to(revision, get_real_ip(request), request.user)
492490 else:
491 article.revert_to(revision, get_real_ip(request))
492 return redirect(article)
493 # An article with this name exists
494 messages.error(
495 request, 'Reverting not possible because an article with name \'%s\' already exists' % old_title)
493 return redirect(article)496 return redirect(article)
494497
495 return HttpResponseNotAllowed(['POST'])498 return HttpResponseNotAllowed(['POST'])
@@ -622,3 +625,50 @@
622 dmp.diff_cleanupSemantic(diffs)625 dmp.diff_cleanupSemantic(diffs)
623626
624 return HttpResponse(dmp.diff_prettyHtml(diffs), content_type='text/html')627 return HttpResponse(dmp.diff_prettyHtml(diffs), content_type='text/html')
628
629
630def backlinks(request, title):
631 """Simple text search for links in other wiki articles pointing to the
632 current article.
633
634 If we convert WikiWords to markdown wikilinks syntax, this view
635 should be changed to use '[[title]]' for searching.
636
637 """
638
639 # Find old title(s) of this article
640 this_article = Article.objects.get(title=title)
641 changesets = this_article.changeset_set.all()
642 old_titles = []
643 for cs in changesets:
644 if cs.old_title and cs.old_title != title and cs.old_title not in old_titles:
645 old_titles.append(cs.old_title)
646
647 # Differentiate between WikiWords and other
648 m = re.match(r"(!?)(\b[A-Z][a-z]+[A-Z]\w+\b)", title)
649 if m:
650 # title is a 'WikiWord' -> This catches also 'MingW' but we have no such title
651 search_title = re.compile(r"%s" % title)
652 else:
653 # Others must be written like links: '[Wiki Page](/wiki/Wiki Page)'
654 search_title = re.compile(r"\/%s\)" % title)
655
656 # Search for current and previous titles
657 found_old_links = []
658 found_links = []
659 articles_all = Article.objects.all().exclude(title=title)
660 for article in articles_all:
661 match = search_title.search(article.content)
662 if match:
663 found_links.append({'title': article.title})
664
665 for old_title in old_titles:
666 if old_title in article.content:
667 found_old_links.append({'old_title': old_title, 'title': article.title })
668
669 context = {'found_links': found_links,
670 'found_old_links': found_old_links,
671 'name': title}
672 return render_to_response('wiki/backlinks.html',
673 context,
674 context_instance=RequestContext(request))

Subscribers

People subscribed via source and target branches