diff --git a/core/forms.py b/core/forms.py index e7a709db..0d1ca5b7 100644 --- a/core/forms.py +++ b/core/forms.py @@ -43,9 +43,13 @@ class LoginForm(AuthenticationForm): ) class PageForm(forms.ModelForm): - #parent = forms.ModelChoiceField(queryset=Page.objects.all()) - #def __init__(self, *args, **kwargs): - # super(PageForm, self).__init__(*args, **kwargs) + error_css_class = 'error' + required_css_class = 'required' + parent = forms.ModelChoiceField(queryset=Page.objects.all()) + + def __init__(self, *args, **kwargs): + super(PageForm, self).__init__(*args, **kwargs) + self.fields['parent'].required = False class Meta: model = Page @@ -53,11 +57,6 @@ class PageForm(forms.ModelForm): def save(self, commit=True): page = super(PageForm, self).save(commit=False) - if self.cleaned_data['parent'] is not None: - page.full_name = '/'.join([self.cleaned_data['parent'].full_name, self.cleaned_data['name']]) - else: - page.full_name = self.cleaned_data['name'] - page.name = self.cleaned_data['name'].split('/')[-1] if commit: page.save() return page diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index f024ebcb..ef697e90 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -2,9 +2,10 @@ from __future__ import unicode_literals from django.db import migrations, models +import django.contrib.auth.models +import django.db.models.deletion import django.utils.timezone import django.core.validators -import django.contrib.auth.models class Migration(migrations.Migration): @@ -17,28 +18,47 @@ class Migration(migrations.Migration): migrations.CreateModel( name='User', fields=[ - ('id', models.AutoField(primary_key=True, auto_created=True, verbose_name='ID', serialize=False)), + ('id', models.AutoField(serialize=False, verbose_name='ID', auto_created=True, primary_key=True)), ('password', models.CharField(verbose_name='password', max_length=128)), - ('last_login', models.DateTimeField(null=True, blank=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], help_text='Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.', error_messages={'unique': 'A user with that username already exists.'}, verbose_name='username', unique=True, max_length=254)), + ('last_login', models.DateTimeField(blank=True, verbose_name='last login', null=True)), + ('is_superuser', models.BooleanField(verbose_name='superuser status', help_text='Designates that this user has all permissions without explicitly assigning them.', default=False)), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=254, verbose_name='username', validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], unique=True, help_text='Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.')), ('first_name', models.CharField(verbose_name='first name', max_length=30)), ('last_name', models.CharField(verbose_name='last name', max_length=30)), ('email', models.EmailField(verbose_name='email address', unique=True, max_length=254)), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), ('date_of_birth', models.DateTimeField(verbose_name='date of birth')), ('nick_name', models.CharField(blank=True, max_length=30)), - ('groups', models.ManyToManyField(related_query_name='user', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', blank=True, to='auth.Group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(related_query_name='user', help_text='Specific permissions for this user.', related_name='user_set', blank=True, to='auth.Permission', verbose_name='user permissions')), + ('is_staff', models.BooleanField(verbose_name='staff status', help_text='Designates whether the user can log into this admin site.', default=False)), + ('is_active', models.BooleanField(verbose_name='active', help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', default=True)), + ('date_joined', models.DateTimeField(verbose_name='date joined', default=django.utils.timezone.now)), + ('groups', models.ManyToManyField(related_name='user_set', to='auth.Group', blank=True, verbose_name='groups', related_query_name='user', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.')), + ('user_permissions', models.ManyToManyField(related_name='user_set', to='auth.Permission', blank=True, verbose_name='user permissions', related_query_name='user', help_text='Specific permissions for this user.')), ], options={ - 'verbose_name_plural': 'users', 'verbose_name': 'user', + 'verbose_name_plural': 'users', }, managers=[ ('objects', django.contrib.auth.models.UserManager()), ], ), + migrations.CreateModel( + name='Page', + fields=[ + ('full_name', models.CharField(serialize=False, verbose_name='page full name', primary_key=True, max_length=30)), + ('name', models.CharField(verbose_name='page name', max_length=30)), + ('title', models.CharField(blank=True, verbose_name='page title', max_length=255)), + ('content', models.TextField(blank=True, verbose_name='page content')), + ('revision', models.PositiveIntegerField(verbose_name='current revision', default=1)), + ('is_locked', models.BooleanField(verbose_name='page mutex', default=False)), + ('parent', models.ForeignKey(related_name='children', blank=True, null=True, to='core.Page', on_delete=django.db.models.deletion.SET_NULL)), + ], + options={ + 'permissions': (('can_edit', 'Can edit the page'), ('can_view', 'Can view the page')), + }, + ), + migrations.AlterUniqueTogether( + name='page', + unique_together=set([('name', 'parent')]), + ), ] diff --git a/core/migrations/0002_auto_20151119_1533.py b/core/migrations/0002_auto_20151119_1533.py deleted file mode 100644 index ce1396bb..00000000 --- a/core/migrations/0002_auto_20151119_1533.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Page', - fields=[ - ('id', models.AutoField(serialize=False, primary_key=True, auto_created=True, verbose_name='ID')), - ('name', models.CharField(max_length=30, verbose_name='page name')), - ('full_name', models.CharField(max_length=255, verbose_name='full name')), - ('content', models.TextField(blank=True, verbose_name='page content')), - ('revision', models.PositiveIntegerField(default=1, verbose_name='current revision')), - ('is_locked', models.BooleanField(default=False, verbose_name='page mutex')), - ], - options={ - 'permissions': (('can_edit', 'Can edit the page'), ('can_view', 'Can view the page')), - }, - ), - migrations.AlterField( - model_name='user', - name='date_of_birth', - field=models.DateTimeField(default='1970-01-01T00:00:00+01:00', verbose_name='date of birth'), - ), - ] diff --git a/core/migrations/0003_auto_20151119_1635.py b/core/migrations/0003_auto_20151119_1635.py deleted file mode 100644 index d83019df..00000000 --- a/core/migrations/0003_auto_20151119_1635.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import datetime -from django.utils.timezone import utc - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0002_auto_20151119_1533'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='date_of_birth', - field=models.DateTimeField(default=datetime.datetime(1942, 6, 12, 0, 0, tzinfo=utc), verbose_name='date of birth'), - ), - ] diff --git a/core/migrations/0004_page_children.py b/core/migrations/0004_page_children.py deleted file mode 100644 index 4ecd56be..00000000 --- a/core/migrations/0004_page_children.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0003_auto_20151119_1635'), - ] - - operations = [ - migrations.AddField( - model_name='page', - name='children', - field=models.ForeignKey(to='core.Page', related_name='parent', null=True), - ), - ] diff --git a/core/migrations/0005_page_title.py b/core/migrations/0005_page_title.py deleted file mode 100644 index 66916b15..00000000 --- a/core/migrations/0005_page_title.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0004_page_children'), - ] - - operations = [ - migrations.AddField( - model_name='page', - name='title', - field=models.CharField(blank=True, max_length=255, verbose_name='page title'), - ), - ] diff --git a/core/migrations/0006_auto_20151120_0958.py b/core/migrations/0006_auto_20151120_0958.py deleted file mode 100644 index 24c9d79c..00000000 --- a/core/migrations/0006_auto_20151120_0958.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0005_page_title'), - ] - - operations = [ - migrations.RemoveField( - model_name='page', - name='id', - ), - migrations.AlterField( - model_name='page', - name='full_name', - field=models.CharField(primary_key=True, max_length=255, serialize=False, verbose_name='full name'), - ), - ] diff --git a/core/migrations/0007_auto_20151120_1347.py b/core/migrations/0007_auto_20151120_1347.py deleted file mode 100644 index b8b8b83e..00000000 --- a/core/migrations/0007_auto_20151120_1347.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0006_auto_20151120_0958'), - ] - - operations = [ - migrations.RemoveField( - model_name='page', - name='full_name', - ), - migrations.AddField( - model_name='page', - name='id', - field=models.AutoField(default=0, auto_created=True, verbose_name='ID', primary_key=True, serialize=False), - preserve_default=False, - ), - ] diff --git a/core/migrations/0008_auto_20151122_1717.py b/core/migrations/0008_auto_20151122_1717.py deleted file mode 100644 index e1593bc5..00000000 --- a/core/migrations/0008_auto_20151122_1717.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0007_auto_20151120_1347'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='date_of_birth', - field=models.DateTimeField(verbose_name='date of birth'), - ), - ] diff --git a/core/migrations/0009_auto_20151123_0902.py b/core/migrations/0009_auto_20151123_0902.py deleted file mode 100644 index 651bf266..00000000 --- a/core/migrations/0009_auto_20151123_0902.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0008_auto_20151122_1717'), - ] - - operations = [ - migrations.RemoveField( - model_name='page', - name='id', - ), - migrations.AlterField( - model_name='page', - name='name', - field=models.CharField(verbose_name='page name', max_length=30, serialize=False, primary_key=True), - ), - ] diff --git a/core/migrations/0010_auto_20151123_0948.py b/core/migrations/0010_auto_20151123_0948.py deleted file mode 100644 index d6ec0bb9..00000000 --- a/core/migrations/0010_auto_20151123_0948.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0009_auto_20151123_0902'), - ] - - operations = [ - migrations.RenameField( - model_name='page', - old_name='name', - new_name='full_name', - ), - ] diff --git a/core/migrations/0011_page_name.py b/core/migrations/0011_page_name.py deleted file mode 100644 index ad0d0762..00000000 --- a/core/migrations/0011_page_name.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0010_auto_20151123_0948'), - ] - - operations = [ - migrations.AddField( - model_name='page', - name='name', - field=models.CharField(verbose_name='page name', default='guy', max_length=30), - preserve_default=False, - ), - ] diff --git a/core/migrations/0012_auto_20151123_1002.py b/core/migrations/0012_auto_20151123_1002.py deleted file mode 100644 index 6953c967..00000000 --- a/core/migrations/0012_auto_20151123_1002.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0011_page_name'), - ] - - operations = [ - migrations.RemoveField( - model_name='page', - name='children', - ), - migrations.AddField( - model_name='page', - name='parent', - field=models.ForeignKey(null=True, related_name='children', to='core.Page'), - ), - ] diff --git a/core/migrations/0013_auto_20151123_1033.py b/core/migrations/0013_auto_20151123_1033.py deleted file mode 100644 index fbf31b70..00000000 --- a/core/migrations/0013_auto_20151123_1033.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('core', '0012_auto_20151123_1002'), - ] - - operations = [ - migrations.AlterField( - model_name='page', - name='full_name', - field=models.CharField(verbose_name='page full name', primary_key=True, serialize=False, max_length=30), - ), - migrations.AlterField( - model_name='page', - name='parent', - field=models.ForeignKey(on_delete=django.db.models.deletion.SET_NULL, blank=True, to='core.Page', related_name='children', null=True), - ), - ] diff --git a/core/models.py b/core/models.py index c4f6a0b2..777acf76 100644 --- a/core/models.py +++ b/core/models.py @@ -1,8 +1,9 @@ from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager from django.utils.translation import ugettext_lazy as _ -from django.core import validators from django.utils import timezone +from django.core import validators +from django.core.exceptions import ValidationError from datetime import datetime class User(AbstractBaseUser, PermissionsMixin): @@ -117,12 +118,57 @@ class Page(models.Model): parent = models.ForeignKey('self', related_name="children", null=True, blank=True, on_delete=models.SET_NULL) class Meta: + unique_together = ('name', 'parent') permissions = ( ("can_edit", "Can edit the page"), ("can_view", "Can view the page"), ) + @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() + + 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) + """ + if '/' in self.name: + self.name = self.name.split('/')[-1] + if self.full_name is None or self.full_name == "": + if self.parent is None: + self.full_name = self.name + else: + self.full_name = self.parent.get_full_name()+'/'+self.name + self.full_name.strip('/') + if self.full_name.split('/')[-1] != self.name: + self.full_name = '/'.join(['/'.join(self.full_name.split('/')[:-1]), self.name]) + #if Page.objects.filter(name=self.name, parent=self.parent).exists(): + # raise ValidationError("Duplicate Page") + super(Page, self).clean() + print("fullname: "+self.full_name) + print("name: "+self.name) + + def save(self, *args, **kwargs): + self.full_clean() + super(Page, self).save(*args, **kwargs) + def __str__(self): + return self.get_full_name() + + def get_full_name(self): return self.full_name def get_display_name(self): diff --git a/core/templates/core/page.html b/core/templates/core/page.html index 19d17dd4..6068061e 100644 --- a/core/templates/core/page.html +++ b/core/templates/core/page.html @@ -15,7 +15,7 @@
You're seeing the page {{ page.get_display_name }}