Fix wiki, plus clean up and add tests

This commit is contained in:
Skia 2015-11-24 10:53:16 +01:00
parent 8753e020a1
commit 9a9541088d
6 changed files with 137 additions and 19 deletions

1
core/fixtures/pages.json Normal file
View File

@ -0,0 +1 @@
[{"model": "core.page", "pk": 1, "fields": {"title": "TROLL", "full_name": "guy2", "content": "ZZZZZZZZZZZZZZZZZZZZZ", "name": "guy2", "parent": null, "revision": 1, "is_locked": false}}, {"model": "core.page", "pk": 2, "fields": {"title": "Bibou", "full_name": "guy/bibou", "content": "Bibou Troll", "name": "bibou", "parent": 4, "revision": 1, "is_locked": false}}, {"model": "core.page", "pk": 3, "fields": {"title": "Troll", "full_name": "guy/bibou/troll", "content": "blbbllblbl", "name": "troll", "parent": 2, "revision": 1, "is_locked": false}}, {"model": "core.page", "pk": 4, "fields": {"title": "TROLL", "full_name": "guy", "content": "", "name": "guy", "parent": null, "revision": 1, "is_locked": false}}, {"model": "core.page", "pk": 5, "fields": {"title": "Bibou", "full_name": "bibou", "content": "", "name": "bibou", "parent": null, "revision": 1, "is_locked": false}}, {"model": "core.page", "pk": 6, "fields": {"title": "Bibou-Guy", "full_name": "bibou/guy", "content": "Bwahahahahahaha", "name": "guy", "parent": 5, "revision": 1, "is_locked": false}}]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='page',
name='full_name',
field=models.CharField(blank=True, verbose_name='page name', max_length=255),
),
]

View File

@ -109,12 +109,25 @@ class User(AbstractBaseUser, PermissionsMixin):
class Page(models.Model):
"""
The page class to build a Wiki
Each page may have a parent and it's URL is of the form my.site/page/<grd_pa>/<parent>/<mypage>
It has an ID field, but don't use it, since it's only there for DB part, and because compound primary key is
awkward!
Prefere querying pages with Page.get_page_by_full_name()
Be careful with the full_name attribute: this field may not be valid until you call save(). It's made for fast
query, but don't rely on it when playing with a Page object, use get_full_name() instead!
"""
name = models.CharField(_('page name'), max_length=30, blank=False)
title = models.CharField(_("page title"), max_length=255, blank=True)
content = models.TextField(_("page content"), blank=True)
revision = models.PositiveIntegerField(_("current revision"), default=1)
is_locked = models.BooleanField(_("page mutex"), default=False)
parent = models.ForeignKey('self', related_name="children", null=True, blank=True, on_delete=models.SET_NULL)
# Attention: this field may not be valid until you call save(). It's made for fast query, but don't rely on it when
# playing with a Page object, use get_full_name() instead!
full_name = models.CharField(_('page name'), max_length=255, blank=True)
class Meta:
unique_together = ('name', 'parent')
@ -125,38 +138,43 @@ class Page(models.Model):
@staticmethod
def get_page_by_full_name(name):
parent_name = '/'.join(name.split('/')[:-1])
name = name.split('/')[-1]
if parent_name == "":
qs = Page.objects.filter(name=name, parent=None)
else:
qs = Page.objects.filter(name=name, parent__name=parent_name)
return qs.first()
"""
Quicker to get a page with that method rather than building the request every time
"""
return Page.objects.filter(full_name=name).first()
def __init__(self, *args, **kwargs):
super(Page, self).__init__(*args, **kwargs)
def clean(self):
"""
This function maintains coherence between full_name, name, and parent.full_name
Be careful modifying it, it could break the entire page table!
This function is mandatory since Django does not support compound primary key,
otherwise, Page class would have had PRIMARY_KEY(name, parent)
Cleans up only the name for the moment, but this can be used to make any treatment before saving the object
"""
if '/' in self.name:
self.name = self.name.split('/')[-1]
if Page.objects.exclude(pk=self.pk).filter(full_name=self.get_full_name()).exists():
raise ValidationError(
_('Duplicate page'),
code='duplicate',
)
super(Page, self).clean()
print("name: "+self.name)
def save(self, *args, **kwargs):
self.full_clean()
# This reset the full_name just before saving to maintain a coherent field quicker for queries than the
# recursive method
self.full_name = self.get_full_name()
super(Page, self).save(*args, **kwargs)
def __str__(self):
return self.get_full_name()
def get_full_name(self):
"""
Computes the real full_name of the page based on its name and its parent's name
You can and must rely on this function when working on a page object that is not freshly fetched from the DB
(For example when treating a Page object coming from a form)
"""
if self.parent is None:
return self.name
return '/'.join([self.parent.get_full_name(), self.name])

View File

@ -148,3 +148,64 @@ class UserRegistrationTest(SimpleTestCase):
response = c.post(reverse('core:login'), {'username': 'gcarlier', 'password': 'guy'})
self.assertTrue(response.status_code == 200)
self.assertTrue('LOGIN_FAIL' in str(response.content))
def test_create_page_ok(self):
"""
Should create a page correctly
"""
c = Client()
response = c.post(reverse('core:page_edit', kwargs={'page_name': 'guy'}), {'parent': '',
'name': 'guy',
'title': 'Guy',
'Content': 'Guyéuyuyé',
})
self.assertTrue(response.status_code == 200)
self.assertTrue('PAGE_SAVED' in str(response.content))
def test_create_child_page_ok(self):
"""
Should create a page correctly
"""
c = Client()
c.post(reverse('core:page_edit', kwargs={'page_name': 'guy'}), {'parent': '',
'name': 'guy',
'title': 'Guy',
'Content': 'Guyéuyuyé',
})
response = c.post(reverse('core:page_edit', kwargs={'page_name': 'guy/bibou'}), {'parent': '1',
'name': 'bibou',
'title': 'Bibou',
'Content':
'Bibibibiblblblblblbouuuuuuuuu',
})
self.assertTrue(response.status_code == 200)
self.assertTrue('PAGE_SAVED' in str(response.content))
def test_access_child_page_ok(self):
"""
Should display a page correctly
"""
c = Client()
c.post(reverse('core:page_edit', kwargs={'page_name': 'guy'}), {'parent': '',
'name': 'guy',
'title': 'Guy',
'Content': 'Guyéuyuyé',
})
c.post(reverse('core:page_edit', kwargs={'page_name': 'guy/bibou'}), {'parent': '1',
'name': 'bibou',
'title': 'Bibou',
'Content':
'Bibibibiblblblblblbouuuuuuuuu',
})
response = c.get(reverse('core:page', kwargs={'page_name': 'guy/bibou'}))
self.assertTrue(response.status_code == 200)
self.assertTrue('PAGE_FOUND : Bibou' in str(response.content))
def test_access_page_not_found(self):
"""
Should not display a page correctly
"""
c = Client()
response = c.get(reverse('core:page', kwargs={'page_name': 'swagg'}))
self.assertTrue(response.status_code == 200)
self.assertTrue('PAGE_NOT_FOUND' in str(response.content))

View File

@ -64,12 +64,15 @@ def login(request):
def logout(request):
"""
The logout view:w
The logout view
"""
auth_logout(request)
return redirect('core:index')
def user(request, user_id=None):
"""
Display a user's profile
"""
context = {'title': 'View a user'}
if user_id == None:
context['user_list'] = User.objects.all
@ -78,6 +81,9 @@ def user(request, user_id=None):
return render(request, "core/user.html", context)
def user_edit(request, user_id=None):
"""
This view allows a user, or the allowed users to modify a profile
"""
user_id = int(user_id)
context = {'title': 'Edit a user'}
if user_id is not None:
@ -88,6 +94,9 @@ def user_edit(request, user_id=None):
return user(request, user_id)
def page(request, page_name=None):
"""
This view displays a page or the link to create it if 404
"""
context = {'title': 'View a Page'}
if page_name == None:
context['page_list'] = Page.objects.all
@ -96,21 +105,30 @@ def page(request, page_name=None):
if context['page'] is not None:
context['view_page'] = True
context['title'] = context['page'].title
context['test'] = "PAGE_FOUND"
context['tests'] = "PAGE_FOUND : "+context['page'].title
else:
context['title'] = "This page does not exist"
context['new_page'] = page_name
context['test'] = "PAGE_NOT_FOUND"
context['tests'] = "PAGE_NOT_FOUND"
return render(request, "core/page.html", context)
def page_edit(request, page_name=None):
"""
page_edit view, able to create a page, save modifications, and display the page ModelForm
"""
context = {'title': 'Edit a page',
'page_name': page_name}
p = Page.get_page_by_full_name(page_name)
# New page
if p == None:
# TODO: guess page name by splitting on '/'
# Same for the parent, try to guess
p = Page(name=page_name)
parent_name = '/'.join(page_name.split('/')[:-1])
name = page_name.split('/')[-1]
if parent_name == "":
p = Page(name=name)
else:
parent = Page.get_page_by_full_name(parent_name)
p = Page(name=name, parent=parent)
# Saving page
if request.method == 'POST':
f = PageForm(request.POST, instance=p)
if f.is_valid():
@ -118,6 +136,7 @@ def page_edit(request, page_name=None):
context['tests'] = "PAGE_SAVED"
else:
context['tests'] = "PAGE_NOT_SAVED"
# Default: display the edit form without change
else:
context['tests'] = "POST_NOT_RECEIVED"
f = PageForm(instance=p)