Skip to content
This repository has been archived by the owner on May 7, 2019. It is now read-only.

Commit

Permalink
Added login and logout views, more UI changes, added thread and post …
Browse files Browse the repository at this point in the history
…count to forum and thread respectively
  • Loading branch information
nylar committed May 26, 2015
1 parent c98e865 commit 6fc604f
Show file tree
Hide file tree
Showing 23 changed files with 226 additions and 22 deletions.
9 changes: 9 additions & 0 deletions fora/mixins.py
@@ -0,0 +1,9 @@
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator


class LoginRequiredMixin(object):

@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
7 changes: 6 additions & 1 deletion fora/settings.py
Expand Up @@ -13,6 +13,9 @@
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

from django.core.urlresolvers import reverse_lazy


BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


Expand All @@ -29,6 +32,8 @@

AUTH_USER_MODEL = "users.User"

LOGIN_URL = reverse_lazy('users:login')

# Application definition

INSTALLED_APPS = (
Expand All @@ -41,10 +46,10 @@

'compressor',

'users',
'forums',
'threads',
'posts',
'users',
)

MIDDLEWARE_CLASSES = (
Expand Down
41 changes: 39 additions & 2 deletions fora/static/css/main.scss
Expand Up @@ -9,9 +9,46 @@ input {
line-height: 1.5;
}

@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}

.pull-left {
float: left;
}

.pull-right {
float: right;
}

nav {
background: #546A76;
margin-bottom: 50px;

ul {
li {
display: inline-block;
a {
color: #BFD4E7;
display: block;
padding: 21px 20px;
text-decoration: none;

&:hover {
background: #3F535D;
}
}
}
}
@include clearfix;
}

.wrap {
margin: 0 auto;
padding-top: 100px;
width: 80%;
}

Expand Down Expand Up @@ -158,7 +195,7 @@ table {
border: 1px solid #BFBFBF;

a {
color: #007FFB;
color: #006BFA;
font-weight: 600;
text-decoration: none;

Expand Down
12 changes: 12 additions & 0 deletions fora/tests/base.py
Expand Up @@ -7,9 +7,21 @@

class BaseTestCase(TestCase):

_password = 'secret'

def setUp(self):
self.user = get_user_model().objects.create_user(
username='user', password=self._password)

def tearDown(self):
get_user_model().objects.all().delete()
Post.objects.all()
Thread.objects.all().delete()
Forum.objects.all().delete()
super(BaseTestCase, self).tearDown()

def _add_session_to_request(self, request):
from django.contrib.sessions.middleware import SessionMiddleware
middleware = SessionMiddleware()
middleware.process_request(request)
request.session.save()
3 changes: 3 additions & 0 deletions forums/models.py
Expand Up @@ -33,5 +33,8 @@ def save(self, *args, **kwargs):
def threads(self):
return self.thread_set.all()

def thread_count(self):
return self.thread_set.count()

def moderator_list(self):
return self.moderators.all()
6 changes: 5 additions & 1 deletion forums/templates/forums/forum_detail.html
Expand Up @@ -13,13 +13,17 @@ <h2>{{ forum.name }}</h2>
<table>
<thead>
<tr>
<th>Thread</th>
<th>Subject</th>
<th>Author</th>
<th>Posts</th>
</tr>
</thead>
<tbody>
{% for thread in forum.threads %}
<tr>
<td><a href="{% url 'threads:show' thread.slug %}">{{ thread.subject }}</a></td>
<td><a href="{% url 'users:profile' thread.author.username %}">{{ thread.author.username }}</td>
<td>{{ thread.post_count }}</td>
</tr>
{% empty %}
<tr>
Expand Down
2 changes: 2 additions & 0 deletions forums/templates/forums/forum_list.html
Expand Up @@ -9,6 +9,7 @@
<tr>
<th>Name</th>
<th>Description</th>
<th>Threads</th>
</tr>
</thead>
<tbody>
Expand All @@ -26,6 +27,7 @@
{% endif %}
</td>
<td><span class="forum-description">{{ forum.description }}</span></td>
<td>{{ forum.thread_count }}</td>
</tr>
{% empty %}
<tr>
Expand Down
12 changes: 12 additions & 0 deletions forums/tests/test_urls.py
Expand Up @@ -10,29 +10,41 @@ def setUp(self):
super(ForumUrlsTestCase, self).setUp()
self.client = Client()

def tearDown(self):
self.client.logout()
super(ForumUrlsTestCase, self).tearDown()

def test_index_url(self):
response = self.client.get(reverse('forums:index'))
self.assertEqual(response.status_code, 200)

def test_new_url(self):
self.client.login(
username=self.user.username, password=self._password)
response = self.client.get(reverse('forums:new'))
self.assertEqual(response.status_code, 200)

def test_update_url(self):
self.client.login(
username=self.user.username, password=self._password)
f = Forum.objects.create(name='Test', description='Test', active=True)
response = self.client.get(
reverse('forums:update', kwargs={'slug': f.slug})
)
self.assertEqual(response.status_code, 200)

def test_update_url_not_found(self):
self.client.login(
username=self.user.username, password=self._password)
f = Forum.objects.create(name='Test', description='Test', active=False)
response = self.client.get(
reverse('forums:update', kwargs={'slug': f.slug})
)
self.assertEqual(response.status_code, 404)

def test_visibility_url(self):
self.client.login(
username=self.user.username, password=self._password)
f = Forum.objects.create(
name='Visible',
description='I am visible',
Expand Down
8 changes: 8 additions & 0 deletions forums/tests/test_views.py
Expand Up @@ -46,6 +46,7 @@ def setUp(self):

def test_get_new_view(self):
request = self.factory.get('/')
request.user = self.user
response = NewForumView.as_view()(request)
response.render()

Expand All @@ -65,13 +66,15 @@ def test_post_form(self):
'name': 'My Forum',
'description': 'My forum containing my threads'
})
request.user = self.user
response = NewForumView.as_view()(request)

self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, reverse('forums:index'))

def test_post_form_invalid(self):
request = self.factory.post(reverse('forums:new'), data={})
request.user = self.user
response = NewForumView.as_view()(request)
response.render()

Expand All @@ -94,6 +97,7 @@ def setUp(self):

def test_get_update_view(self):
request = self.factory.get('/')
request.user = self.user
response = UpdateForumView.as_view()(request, slug=self.forum.slug)
response.render()

Expand All @@ -112,13 +116,15 @@ def test_post_form(self):
'name': 'Updated Forum',
'description': self.forum.description
})
request.user = self.user
response = UpdateForumView.as_view()(request, slug=self.forum.slug)

self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, reverse('forums:index'))

def test_post_form_invalid(self):
request = self.factory.post('/', data={})
request.user = self.user
response = UpdateForumView.as_view()(request, slug=self.forum.slug)
response.render()

Expand All @@ -141,6 +147,7 @@ def setUp(self):

def test_get_visibility_view(self):
request = self.factory.get('/')
request.user = self.user
response = ChangeForumVisibilityView.as_view()(
request,
slug=self.forum.slug
Expand All @@ -157,6 +164,7 @@ def test_post_form(self):
request = self.factory.post('/', data={
'active': False,
})
request.user = self.user
response = ChangeForumVisibilityView.as_view()(
request,
slug=self.forum.slug
Expand Down
7 changes: 4 additions & 3 deletions forums/views.py
Expand Up @@ -3,6 +3,7 @@
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.list import ListView
from fora.mixins import LoginRequiredMixin
from forums.models import Forum


Expand All @@ -11,7 +12,7 @@ class ForumIndexView(ListView):
model = Forum


class NewForumView(CreateView):
class NewForumView(LoginRequiredMixin, CreateView):
model = Forum
fields = ['name', 'description', 'active']

Expand All @@ -29,7 +30,7 @@ def get_object(self):
raise Http404('No Forum matches the given query.')


class UpdateForumView(ForumMixin, UpdateView):
class UpdateForumView(LoginRequiredMixin, ForumMixin, UpdateView):
context_object_name = 'forum'
model = Forum
fields = ['name', 'description']
Expand All @@ -38,7 +39,7 @@ def get_success_url(self):
return reverse('forums:index')


class ChangeForumVisibilityView(UpdateView):
class ChangeForumVisibilityView(LoginRequiredMixin, UpdateView):
context_object_name = 'forum'
model = Forum
fields = ['active']
Expand Down
3 changes: 3 additions & 0 deletions threads/models.py
Expand Up @@ -30,6 +30,9 @@ def __unicode__(self):
def posts(self):
return self.post_set.all()

def post_count(self):
return self.post_set.count()


@receiver(post_save, sender=Thread)
def generate_slug(sender, instance, created, **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion threads/templates/threads/thread_detail.html
@@ -1,7 +1,7 @@
{% extends "base.html" %}

{% block content %}
<h1>{{ thread.subject }}</h1>
<h2>{{ thread.subject }}</h2>
<p>Forum: <a href="{% url 'forums:show' thread.forum.slug %}">{{ thread.forum.name }}</a></p>
<p>{{ thread.created }}</p>
{% endblock content %}
8 changes: 8 additions & 0 deletions threads/tests/test_models.py
Expand Up @@ -45,3 +45,11 @@ def test_posts(self):
posts = self.thread.posts()
self.assertEqual(len(posts), 2)
self.assertEqual(list(posts), [p1, p2])

def test_post_count(self):
post_count = self.thread.post_count()
self.assertEqual(post_count, 0)

Post.objects.create(message='p1', thread=self.thread)
post_count = self.thread.post_count()
self.assertEqual(post_count, 1)
6 changes: 6 additions & 0 deletions threads/tests/test_urls.py
Expand Up @@ -11,7 +11,13 @@ def setUp(self):
super(ThreadUrlsTestCase, self).setUp()
self.client = Client()

def tearDown(self):
self.client.logout()
super(ThreadUrlsTestCase, self).tearDown()

def test_new_url(self):
self.client.login(
username=self.user.username, password=self._password)
response = self.client.get(reverse('threads:new'))
self.assertEqual(response.status_code, 200)

Expand Down
2 changes: 2 additions & 0 deletions threads/tests/test_views.py
Expand Up @@ -14,6 +14,7 @@ def setUp(self):

def test_get_new_view(self):
request = self.factory.get('/')
request.user = self.user
response = NewThreadView.as_view()(request)
response.render()

Expand All @@ -34,6 +35,7 @@ def test_post_form(self):
'subject': 'My thread',
'forum': forum.pk
})
request.user = self.user
response = NewThreadView.as_view()(request)

thread = Thread.objects.get(pk=1)
Expand Down
9 changes: 8 additions & 1 deletion threads/views.py
Expand Up @@ -2,6 +2,7 @@
from django.http import Http404
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView
from fora.mixins import LoginRequiredMixin
from threads.models import Thread


Expand All @@ -15,11 +16,17 @@ def get_object(self):
raise Http404('No Thread matches the given query.')


class NewThreadView(CreateView):
class NewThreadView(LoginRequiredMixin, CreateView):
context_object_name = 'thread'
model = Thread
fields = ['subject', 'forum']

def form_valid(self, form):
f = form.save(commit=False)
f.author = self.request.user
f.save()
return super(NewThreadView, self).form_valid(form)

def get_success_url(self):
return reverse('threads:show', kwargs={'slug': self.object.slug})

Expand Down

0 comments on commit 6fc604f

Please sign in to comment.