SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 65465a6b authored by Jean-Sébastien Caux's avatar Jean-Sébastien Caux
Browse files

Add Forum and Post models (+ their admin)

parent 0d298635
No related branches found
No related tags found
No related merge requests found
...@@ -94,6 +94,7 @@ INSTALLED_APPS = ( ...@@ -94,6 +94,7 @@ INSTALLED_APPS = (
'django_celery_results', 'django_celery_results',
'django_celery_beat', 'django_celery_beat',
'finances', 'finances',
'forums',
'guides', 'guides',
'invitations', 'invitations',
'journals', 'journals',
......
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
from django.contrib import admin from django.contrib import admin
# Register your models here. from .models import Forum, Post
class ForumAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('name',)}
search_fields = ['name',]
admin.site.register(Forum, ForumAdmin)
class PostAdmin(admin.ModelAdmin):
search_fields = ['posted_by', 'subject', 'text']
admin.site.register(Post, PostAdmin)
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2019-03-03 09:36
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Forum',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=256)),
('slug', models.SlugField(allow_unicode=True)),
('publicly_visible', models.BooleanField(default=False)),
('parent_object_id', models.PositiveIntegerField(blank=True, null=True)),
('moderators', models.ManyToManyField(related_name='moderated_forums', to=settings.AUTH_USER_MODEL)),
('parent_content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
options={
'ordering': ['name'],
},
),
migrations.CreateModel(
name='Post',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('posted_on', models.DateTimeField(default=django.utils.timezone.now)),
('needs_vetting', models.BooleanField(default=True)),
('parent_object_id', models.PositiveIntegerField()),
('subject', models.CharField(max_length=256)),
('text', models.TextField()),
('parent_content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('posted_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('vetted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vetted_posts', to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ['posted_on'],
},
),
]
...@@ -2,50 +2,87 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" ...@@ -2,50 +2,87 @@ __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3" __license__ = "AGPL v3"
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
class Forum(models.Model): class Forum(models.Model):
""" """
A Forum is a discussion place for a specified set of Users, A Forum is a discussion location for a defined set of Users.
with access specified on a per-Group or per-User access.
A Forum instance can be publicly visible. For publicly invisible forums,
as well as for thread creation and posting rights,
access is specified flexibly on a per-Group and/or per-User basis
via object-level permissions (through the django-guardian required app).
Forums can be related to parent/children via parent [GenericForeignKey]
and child_forums [GenericRelation] fields.
Similarly, Posts in a Forum are listed in the posts [GenericRelation] field.
""" """
name = models.CharField(max_length=256) name = models.CharField(max_length=256)
slug = models.SlugField(allow_unicode=True) slug = models.SlugField(allow_unicode=True)
accessible_to_group = models.ManyToManyField('auth.Group',
related_name='group_forums',
blank=True)
accessible_to_users = models.ManyToManyField('auth.User',
related_name='user_forums',
blank=True)
publicly_visible = models.BooleanField(default=False) publicly_visible = models.BooleanField(default=False)
moderators = models.ManyToManyField('auth.User', related_name='moderated_forums')
parent_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
blank=True, null=True)
parent_object_id = models.PositiveIntegerField(blank=True, null=True)
parent = GenericForeignKey('parent_content_type', 'parent_object_id')
class Meeting(Forum): child_forums = GenericRelation('forums.Forum',
""" content_type_field='parent_content_type',
A Meeting is like a Forum, but with a fixed time span. object_id_field='parent_object_id',
""" related_query_name='parent_forums')
date_from = models.DateField() posts = GenericRelation('forums.Post',
date_until = models.DateField() content_type_field='parent_content_type',
preamble = models.TextField() object_id_field='parent_object_id',
minutes = models.TextField(blank=True, null=True) related_query_name='parent_forums')
class Meta:
ordering = ['name',]
class Thread(models.Model): def __str__(self):
""" return self.slug
A Thread is a container for Posts.
"""
theme = models.CharField(max_length=256)
slug = models.SlugField()
forum = models.ForeignKey('forums.Forum')
class Post(models.Model): class Post(models.Model):
""" """
A comment, feedback, question, ... pertaining to a Thread A comment, feedback, question or similar, with a specified parent object.
If the Post is submitted by Admin, Advisory Board members or Fellows,
it is marked as not needing vetting before becoming visible.
Similarly, for Posts created by organizations.Contacts, no vetting is required.
Otherwise, e.g. for Contributors-submitted Posts to a publicly-visible
Forum, vetting by Admin is required.
A Post must have a parent object (represented here as a GenericForeignKey).
If the parent is a Forum, the Post is interpreted as the head of
a new discussion thread. If the parent is a Post, then it is interpreted as
part of an ongoing thread.
The text field can contain ReStructuredText markup, formatted in templates
through the django-docutils required app.
""" """
posted_by = models.ForeignKey('auth.User') posted_by = models.ForeignKey('auth.User', on_delete=models.CASCADE)
posted_on = models.DateTimeField(default=timezone.now) posted_on = models.DateTimeField(default=timezone.now)
needs_vetting = models.BooleanField(default=True)
vetted_by = models.ForeignKey('auth.User', related_name='vetted_posts',
blank=True, null=True, on_delete=models.PROTECT)
parent_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
parent_object_id = models.PositiveIntegerField()
parent = GenericForeignKey('parent_content_type', 'parent_object_id')
followup_posts = GenericRelation('forums.Post',
content_type_field='parent_content_type',
object_id_field='parent_object_id',
related_query_name='parent_posts')
subject = models.CharField(max_length=256)
text = models.TextField() text = models.TextField()
class Meta:
ordering = ['posted_on',]
def __str__(self):
return '%s: %s' % (self.posted_by, self.subject[:32])
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment