mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-22 06:03:20 +00:00
Add Forum
This commit is contained in:
parent
fcaa740710
commit
ea52462217
@ -18,6 +18,7 @@ from subscription.models import Subscription
|
||||
from counter.models import Customer, ProductType, Product, Counter
|
||||
from com.models import Sith, Weekmail
|
||||
from election.models import Election, Role, Candidature, ElectionList
|
||||
from forum.models import Forum, ForumMessage
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@ -429,3 +430,13 @@ Welcome to the wiki page!
|
||||
cand = Candidature(role=pres, user=sli, election_list=listeT, program="En fait j'aime pas l'info, je voulais faire GMC")
|
||||
cand.save()
|
||||
|
||||
# Forum
|
||||
room = Forum(name="Salon de discussions", description="Pour causer de tout", is_category=True)
|
||||
room.save()
|
||||
Forum(name="AE", description="Réservé au bureau AE", parent=room).save()
|
||||
Forum(name="BdF", description="Réservé au bureau BdF", parent=room).save()
|
||||
Forum(name="Hall de discussions", description="Pour toutes les discussions", parent=room).save()
|
||||
various = Forum(name="Divers", description="Pour causer de rien", is_category=True)
|
||||
various.save()
|
||||
Forum(name="Promos", description="Réservé aux Promos", parent=various).save()
|
||||
|
||||
|
@ -91,7 +91,7 @@
|
||||
<a href="https://ae.utbm.fr/matmatronch/">{% trans %}Matmatronch{% endtrans %}</a>
|
||||
<a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a>
|
||||
<a href="{{ url('sas:main') }}">{% trans %}SAS{% endtrans %}</a>
|
||||
<a href="https://ae.utbm.fr/forum2/">{% trans %}Forum{% endtrans %}</a>
|
||||
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
|
||||
<a href="{{ url('core:page', "services") }}">{% trans %}Services{% endtrans %}</a>
|
||||
<a href="{{ url('core:file_list') }}">{% trans %}Files{% endtrans %}</a>
|
||||
<a href="https://ae.utbm.fr/article.php?name=liens">{% trans %}Sponsors{% endtrans %}</a>
|
||||
|
0
forum/__init__.py
Normal file
0
forum/__init__.py
Normal file
3
forum/admin.py
Normal file
3
forum/admin.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
51
forum/migrations/0001_initial.py
Normal file
51
forum/migrations/0001_initial.py
Normal file
@ -0,0 +1,51 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('core', '0019_preferences_receive_weekmail'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Forum',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(verbose_name='name', max_length=64)),
|
||||
('description', models.CharField(default='', verbose_name='description', max_length=256)),
|
||||
('is_category', models.BooleanField(default=False, verbose_name='is a category')),
|
||||
('edit_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='editable_forums')),
|
||||
('owner_group', models.ForeignKey(to='core.Group', default=4, related_name='owned_forums')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, to='forum.Forum', related_name='children')),
|
||||
('view_groups', models.ManyToManyField(to='core.Group', blank=True, related_name='viewable_forums')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ForumMessage',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
|
||||
('title', models.CharField(default='', blank=True, verbose_name='title', max_length=64)),
|
||||
('message', models.TextField(verbose_name='message', default='')),
|
||||
('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='forum_messages')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ForumTopic',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)),
|
||||
('author', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='forum_topics')),
|
||||
('forum', models.ForeignKey(to='forum.Forum', related_name='topics')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='forummessage',
|
||||
name='topic',
|
||||
field=models.ForeignKey(to='forum.ForumTopic', related_name='messages'),
|
||||
),
|
||||
]
|
19
forum/migrations/0002_forumtopic_title.py
Normal file
19
forum/migrations/0002_forumtopic_title.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('forum', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='forumtopic',
|
||||
name='title',
|
||||
field=models.CharField(verbose_name='title', max_length=64, default=''),
|
||||
),
|
||||
]
|
24
forum/migrations/0003_auto_20170121_0311.py
Normal file
24
forum/migrations/0003_auto_20170121_0311.py
Normal file
@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('forum', '0002_forumtopic_title'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='forumtopic',
|
||||
options={'ordering': ['messages__date', '-id']},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='forummessage',
|
||||
name='date',
|
||||
field=models.DateTimeField(verbose_name='date', default=django.utils.timezone.now),
|
||||
),
|
||||
]
|
19
forum/migrations/0004_forumtopic_description.py
Normal file
19
forum/migrations/0004_forumtopic_description.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('forum', '0003_auto_20170121_0311'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='forumtopic',
|
||||
name='description',
|
||||
field=models.CharField(max_length=256, verbose_name='description', default=''),
|
||||
),
|
||||
]
|
0
forum/migrations/__init__.py
Normal file
0
forum/migrations/__init__.py
Normal file
79
forum/models.py
Normal file
79
forum/models.py
Normal file
@ -0,0 +1,79 @@
|
||||
from django.db import models
|
||||
from django.core import validators
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError, transaction
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils import timezone
|
||||
|
||||
from core.models import User, MetaGroup, Group, SithFile
|
||||
|
||||
class Forum(models.Model):
|
||||
"""
|
||||
The Forum class, made as a tree to allow nice tidy organization
|
||||
"""
|
||||
name = models.CharField(_('name'), max_length=64)
|
||||
description = models.CharField(_('description'), max_length=256, default="")
|
||||
is_category = models.BooleanField(_('is a category'), default=False)
|
||||
parent = models.ForeignKey('Forum', related_name='children', null=True, blank=True)
|
||||
owner_group = models.ForeignKey(Group, related_name="owned_forums",
|
||||
default=settings.SITH_GROUP_COM_ADMIN_ID)
|
||||
edit_groups = models.ManyToManyField(Group, related_name="editable_forums", blank=True)
|
||||
view_groups = models.ManyToManyField(Group, related_name="viewable_forums", blank=True)
|
||||
|
||||
def check_loop(self):
|
||||
"""Raise a validation error when a loop is found within the parent list"""
|
||||
objs = []
|
||||
cur = self
|
||||
while cur.parent is not None:
|
||||
if cur in objs:
|
||||
raise ValidationError(_('You can not make loops in forums'))
|
||||
objs.append(cur)
|
||||
cur = cur.parent
|
||||
|
||||
def clean(self):
|
||||
self.check_loop()
|
||||
|
||||
def __str__(self):
|
||||
return "%s" % (self.name)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('forum:view_forum', kwargs={'forum_id': self.id})
|
||||
|
||||
def get_parent_list(self):
|
||||
l = []
|
||||
p = self.parent
|
||||
while p is not None:
|
||||
l.append(p)
|
||||
p = p.parent
|
||||
return l
|
||||
|
||||
class ForumTopic(models.Model):
|
||||
forum = models.ForeignKey(Forum, related_name='topics')
|
||||
author = models.ForeignKey(User, related_name='forum_topics')
|
||||
title = models.CharField(_("title"), default="", max_length=64)
|
||||
description = models.CharField(_('description'), max_length=256, default="")
|
||||
|
||||
class Meta:
|
||||
ordering = ['-id']
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('forum:view_topic', kwargs={'topic_id': self.id})
|
||||
|
||||
class ForumMessage(models.Model):
|
||||
"""
|
||||
"A ForumMessage object is a message in the forum" Cpt. Obvious
|
||||
"""
|
||||
topic = models.ForeignKey(ForumTopic, related_name='messages')
|
||||
author = models.ForeignKey(User, related_name='forum_messages')
|
||||
title = models.CharField(_("title"), default="", max_length=64, blank=True)
|
||||
message = models.TextField(_("message"), default="")
|
||||
date = models.DateTimeField(_('date'), default=timezone.now)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-id']
|
||||
|
||||
def get_absolute_url(self):
|
||||
return self.topic.get_absolute_url()
|
||||
|
44
forum/templates/forum/forum.jinja
Normal file
44
forum/templates/forum/forum.jinja
Normal file
@ -0,0 +1,44 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from 'forum/macros.jinja' import display_forum %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style type="text/css" media="all">
|
||||
.topic {
|
||||
border: solid skyblue 1px;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.forum {
|
||||
background: lightblue;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.category {
|
||||
background: skyblue;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p>{{ forum.get_parent_list() }}</p>
|
||||
<h3>{{ forum.name }}</h3>
|
||||
<a href="{{ url('forum:new_forum') }}?parent={{ forum.id }}">New forum</a>
|
||||
{% for f in forum.children.all() %}
|
||||
{{ display_forum(f) }}
|
||||
{% endfor %}
|
||||
{% for t in forum.topics.all() %}
|
||||
<div class="topic">
|
||||
<p>
|
||||
<a href="{{ url('forum:view_topic', topic_id=t.id) }}">View</a>
|
||||
<a href="{{ url('forum:edit_topic', topic_id=t.id) }}">Edit</a>
|
||||
</p>
|
||||
<h5>{{ t.title }}</h5>
|
||||
<p>{{ t.description }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<a href="{{ url('forum:new_topic', forum_id=forum.id) }}">New topic</a>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
14
forum/templates/forum/macros.jinja
Normal file
14
forum/templates/forum/macros.jinja
Normal file
@ -0,0 +1,14 @@
|
||||
{% macro display_forum(forum) %}
|
||||
<div class="forum {% if forum.is_category %}category{% endif %}">
|
||||
<p>
|
||||
{% if not forum.is_category %}
|
||||
<a href="{{ url('forum:view_forum', forum_id=forum.id) }}">View</a>
|
||||
{% endif %}
|
||||
<a href="{{ url('forum:edit_forum', forum_id=forum.id) }}">Edit</a>
|
||||
</p>
|
||||
<h5>{{ forum.name }}</h5>
|
||||
<p>{{ forum.description }}</p>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
33
forum/templates/forum/main.jinja
Normal file
33
forum/templates/forum/main.jinja
Normal file
@ -0,0 +1,33 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
{% from 'core/macros.jinja' import user_profile_link %}
|
||||
{% from 'forum/macros.jinja' import display_forum %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style type="text/css" media="all">
|
||||
.forum {
|
||||
background: lightblue;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.category {
|
||||
background: skyblue;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{% trans %}Forum{% endtrans %}</h3>
|
||||
<a href="{{ url('forum:new_forum') }}">New forum</a>
|
||||
{% for f in forum_list %}
|
||||
<div style="padding: 4px; margin: 4px">
|
||||
{{ display_forum(f) }}
|
||||
{% for c in f.children.all() %}
|
||||
{{ display_forum(c) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
38
forum/templates/forum/topic.jinja
Normal file
38
forum/templates/forum/topic.jinja
Normal file
@ -0,0 +1,38 @@
|
||||
{% extends "core/base.jinja" %}
|
||||
|
||||
{% block head %}
|
||||
{{ super() }}
|
||||
<style type="text/css" media="all">
|
||||
.topic {
|
||||
border: solid skyblue 1px;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.forum {
|
||||
background: lightblue;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.category {
|
||||
background: skyblue;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h3>{{ topic.title }}</h3>
|
||||
<p>{{ topic.description }}</p>
|
||||
<p><a href="{{ url('forum:new_message', topic_id=topic.id) }}">Reply</a></p>
|
||||
{% for m in topic.messages.all() %}
|
||||
<div>
|
||||
<h5>{{ m.title }}</h5>
|
||||
<p><strong>{{ m.author.get_display_name() }}</strong> - {{ m.date|date(DATETIME_FORMAT) }}
|
||||
{{ m.date|time(DATETIME_FORMAT) }} -
|
||||
<a href="{{ url('forum:new_message', topic_id=topic.id) }}?quote_id={{ m.id }}">Reply as quote</a></p>
|
||||
<p>{{ m.message|markdown }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
3
forum/tests.py
Normal file
3
forum/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
16
forum/urls.py
Normal file
16
forum/urls.py
Normal file
@ -0,0 +1,16 @@
|
||||
from django.conf.urls import url, include
|
||||
|
||||
from forum.views import *
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', ForumMainView.as_view(), name='main'),
|
||||
url(r'^new_forum$', ForumCreateView.as_view(), name='new_forum'),
|
||||
url(r'^(?P<forum_id>[0-9]+)$', ForumDetailView.as_view(), name='view_forum'),
|
||||
url(r'^(?P<forum_id>[0-9]+)/edit$', ForumEditView.as_view(), name='edit_forum'),
|
||||
url(r'^(?P<forum_id>[0-9]+)/new_topic$', ForumTopicCreateView.as_view(), name='new_topic'),
|
||||
url(r'^topic/(?P<topic_id>[0-9]+)$', ForumTopicDetailView.as_view(), name='view_topic'),
|
||||
url(r'^topic/(?P<topic_id>[0-9]+)/edit$', ForumTopicEditView.as_view(), name='edit_topic'),
|
||||
url(r'^topic/(?P<topic_id>[0-9]+)/new_message$', ForumMessageCreateView.as_view(), name='new_message'),
|
||||
# url(r'^(?P<club_id>[0-9]+)/tools$', ClubToolsView.as_view(), name='tools'),
|
||||
]
|
||||
|
92
forum/views.py
Normal file
92
forum/views.py
Normal file
@ -0,0 +1,92 @@
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.views.generic import ListView, DetailView, RedirectView
|
||||
from django.views.generic.edit import UpdateView, CreateView, DeleteView
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.urlresolvers import reverse, reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
from django import forms
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
||||
from forum.models import Forum, ForumMessage, ForumTopic
|
||||
|
||||
class ForumMainView(ListView):
|
||||
queryset = Forum.objects.filter(parent=None)
|
||||
template_name = "forum/main.jinja"
|
||||
|
||||
class ForumCreateView(CreateView):
|
||||
model = Forum
|
||||
fields = ['name', 'parent', 'is_category', 'owner_group', 'edit_groups', 'view_groups']
|
||||
template_name = "core/create.jinja"
|
||||
|
||||
def get_initial(self):
|
||||
init = super(ForumCreateView, self).get_initial()
|
||||
parent = Forum.objects.filter(id=self.request.GET['parent']).first()
|
||||
init['parent'] = parent
|
||||
return init
|
||||
|
||||
class ForumEditView(UpdateView):
|
||||
model = Forum
|
||||
pk_url_kwarg = "forum_id"
|
||||
fields = ['name', 'parent', 'is_category', 'owner_group', 'edit_groups', 'view_groups']
|
||||
template_name = "core/edit.jinja"
|
||||
success_url = reverse_lazy('forum:main')
|
||||
|
||||
class ForumDetailView(DetailView):
|
||||
model = Forum
|
||||
template_name = "forum/forum.jinja"
|
||||
pk_url_kwarg = "forum_id"
|
||||
|
||||
class ForumTopicCreateView(CreateView):
|
||||
model = ForumTopic
|
||||
fields = ['title']
|
||||
template_name = "core/create.jinja"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.forum = get_object_or_404(Forum, id=self.kwargs['forum_id'], is_category=False)
|
||||
if not request.user.can_view(self.forum):
|
||||
raise PermissionDenied
|
||||
return super(ForumTopicCreateView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.forum = self.forum
|
||||
form.instance.author = self.request.user
|
||||
return super(ForumTopicCreateView, self).form_valid(form)
|
||||
|
||||
class ForumTopicEditView(UpdateView):
|
||||
model = ForumTopic
|
||||
fields = ['title']
|
||||
pk_url_kwarg = "topic_id"
|
||||
template_name = "core/edit.jinja"
|
||||
|
||||
class ForumTopicDetailView(DetailView):
|
||||
model = ForumTopic
|
||||
pk_url_kwarg = "topic_id"
|
||||
template_name = "forum/topic.jinja"
|
||||
context_object_name = "topic"
|
||||
|
||||
class ForumMessageCreateView(CreateView):
|
||||
model = ForumMessage
|
||||
fields = ['title', 'message']
|
||||
template_name = "core/create.jinja"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.topic = get_object_or_404(ForumTopic, id=self.kwargs['topic_id'])
|
||||
if not request.user.can_view(self.topic):
|
||||
raise PermissionDenied
|
||||
return super(ForumMessageCreateView, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_initial(self):
|
||||
init = super(ForumMessageCreateView, self).get_initial()
|
||||
try:
|
||||
init['message'] = "\n".join([
|
||||
" > " + line for line in ForumMessage.objects.filter(id=self.request.GET['quote_id']).first().message.split('\n')
|
||||
])
|
||||
except: pass
|
||||
return init
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.topic = self.topic
|
||||
form.instance.author = self.request.user
|
||||
return super(ForumMessageCreateView, self).form_valid(form)
|
||||
|
@ -59,6 +59,7 @@ INSTALLED_APPS = (
|
||||
'sas',
|
||||
'com',
|
||||
'election',
|
||||
'forum',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
|
@ -40,6 +40,7 @@ urlpatterns = [
|
||||
url(r'^sas/', include('sas.urls', namespace="sas", app_name="sas")),
|
||||
url(r'^api/v1/', include('api.urls', namespace="api", app_name="api")),
|
||||
url(r'^election/', include('election.urls', namespace="election", app_name="election")),
|
||||
url(r'^forum/', include('forum.urls', namespace="forum", app_name="forum")),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^ajax_select/', include(ajax_select_urls)),
|
||||
url(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
|
Loading…
Reference in New Issue
Block a user