diff options
Diffstat (limited to 'apps/forum')
-rw-r--r-- | apps/forum/admin.py | 2 | ||||
-rw-r--r-- | apps/forum/forms.py | 13 | ||||
-rw-r--r-- | apps/forum/migrations/0002_category_description.py | 19 | ||||
-rw-r--r-- | apps/forum/migrations/0003_auto_20190110_1405.py | 18 | ||||
-rw-r--r-- | apps/forum/migrations/0004_category_color_rgb.py | 18 | ||||
-rw-r--r-- | apps/forum/migrations/0005_auto_20190110_2023.py | 18 | ||||
-rw-r--r-- | apps/forum/migrations/0006_auto_20190111_1002.py | 28 | ||||
-rw-r--r-- | apps/forum/models.py | 22 | ||||
-rw-r--r-- | apps/forum/templatetags/__init__.py | 0 | ||||
-rw-r--r-- | apps/forum/templatetags/timesinceabbr.py | 107 | ||||
-rw-r--r-- | apps/forum/urls.py | 6 | ||||
-rw-r--r-- | apps/forum/views.py | 14 |
12 files changed, 254 insertions, 11 deletions
diff --git a/apps/forum/admin.py b/apps/forum/admin.py index 9fddd4e..1dfe734 100644 --- a/apps/forum/admin.py +++ b/apps/forum/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from .models import Topic, Category, Post +from .forms import CategoryForm @admin.register(Topic) @@ -10,6 +11,7 @@ class TopicAdmin(admin.ModelAdmin): @admin.register(Category) class CategoryAdmin(admin.ModelAdmin): + form = CategoryForm pass diff --git a/apps/forum/forms.py b/apps/forum/forms.py new file mode 100644 index 0000000..655a318 --- /dev/null +++ b/apps/forum/forms.py @@ -0,0 +1,13 @@ +#form.py +from django.forms import ModelForm +from django.forms.widgets import TextInput +from .models import Category + + +class CategoryForm(ModelForm): + class Meta: + model = Category + fields = '__all__' + widgets = { + 'color_rgb': TextInput(attrs={'type': 'color'}), + } diff --git a/apps/forum/migrations/0002_category_description.py b/apps/forum/migrations/0002_category_description.py new file mode 100644 index 0000000..6c13147 --- /dev/null +++ b/apps/forum/migrations/0002_category_description.py @@ -0,0 +1,19 @@ +# Generated by Django 2.1.2 on 2019-01-10 17:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('forum', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='category', + name='description', + field=models.CharField(default='', max_length=350), + preserve_default=False, + ), + ] diff --git a/apps/forum/migrations/0003_auto_20190110_1405.py b/apps/forum/migrations/0003_auto_20190110_1405.py new file mode 100644 index 0000000..446f0a4 --- /dev/null +++ b/apps/forum/migrations/0003_auto_20190110_1405.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2019-01-10 20:05 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('forum', '0002_category_description'), + ] + + operations = [ + migrations.RenameField( + model_name='category', + old_name='title', + new_name='name', + ), + ] diff --git a/apps/forum/migrations/0004_category_color_rgb.py b/apps/forum/migrations/0004_category_color_rgb.py new file mode 100644 index 0000000..04de146 --- /dev/null +++ b/apps/forum/migrations/0004_category_color_rgb.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2019-01-10 20:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('forum', '0003_auto_20190110_1405'), + ] + + operations = [ + migrations.AddField( + model_name='category', + name='color_rgb', + field=models.CharField(blank=True, max_length=20), + ), + ] diff --git a/apps/forum/migrations/0005_auto_20190110_2023.py b/apps/forum/migrations/0005_auto_20190110_2023.py new file mode 100644 index 0000000..3040a48 --- /dev/null +++ b/apps/forum/migrations/0005_auto_20190110_2023.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2019-01-11 02:23 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('forum', '0004_category_color_rgb'), + ] + + operations = [ + migrations.RenameField( + model_name='topic', + old_name='last_post_userj', + new_name='last_post_user', + ), + ] diff --git a/apps/forum/migrations/0006_auto_20190111_1002.py b/apps/forum/migrations/0006_auto_20190111_1002.py new file mode 100644 index 0000000..c1673cb --- /dev/null +++ b/apps/forum/migrations/0006_auto_20190111_1002.py @@ -0,0 +1,28 @@ +# Generated by Django 2.1.2 on 2019-01-11 16:02 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('forum', '0005_auto_20190110_2023'), + ] + + operations = [ + migrations.RenameField( + model_name='post', + old_name='post_body_html', + new_name='body_html', + ), + migrations.RenameField( + model_name='post', + old_name='post_body_json', + new_name='body_json', + ), + migrations.RenameField( + model_name='post', + old_name='post_body_text', + new_name='body_text', + ), + ] diff --git a/apps/forum/models.py b/apps/forum/models.py index d0f6b6f..3a54514 100644 --- a/apps/forum/models.py +++ b/apps/forum/models.py @@ -28,8 +28,10 @@ class CategoryManager(models.Manager): class Category(models.Model): - title = models.CharField(max_length=120) + name = models.CharField(max_length=120) slug = models.SlugField() + description = models.CharField(max_length=350) + color_rgb = models.CharField(max_length=20, blank=True) date_created = models.DateTimeField(auto_now=False, auto_now_add=True) date_updated = models.DateTimeField(auto_now=True, auto_now_add=False) @@ -44,8 +46,11 @@ class Category(models.Model): objects = CategoryManager() - def __unicode__(self): - return self.title + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("forum:category-detail", kwargs={'slug': self.slug}) class TopicManager(models.Manager): @@ -62,10 +67,9 @@ class TopicManager(models.Manager): class Topic(models.Model): - category = models.ForeignKey(Category, on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='topic_user') - last_post_userj= models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='topic_last_post_user', blank=True, null=True) + last_post_user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='topic_last_post_user', blank=True, null=True) highest_post = models.ForeignKey('Post', on_delete=models.CASCADE, related_name='topic_highest_post', blank=True, null=True) title = models.CharField(max_length=255) @@ -119,9 +123,9 @@ class Post(models.Model): ('reply', 'reply'), ) post_type = models.CharField(max_length=60, choices=POST_TYPE_CHOICES) - post_body_text = models.TextField(blank=True, null=False) - post_body_html = models.TextField(blank=True, null=True) - post_body_json = models.TextField(blank=True, null=True) + body_text = models.TextField(blank=True, null=False) + body_html = models.TextField(blank=True, null=True) + body_json = models.TextField(blank=True, null=True) date_created = models.DateTimeField(auto_now=False, auto_now_add=True, blank=True) date_updated = models.DateTimeField(auto_now=True, auto_now_add=False, blank=True) @@ -142,4 +146,4 @@ class Post(models.Model): verbose_name_plural = "Posts" def __str__(self): - return '%s - %s' % (self.raw, self.topic.title) + return '%s - %s' % (self.topic.title, self.id) diff --git a/apps/forum/templatetags/__init__.py b/apps/forum/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/apps/forum/templatetags/__init__.py diff --git a/apps/forum/templatetags/timesinceabbr.py b/apps/forum/templatetags/timesinceabbr.py new file mode 100644 index 0000000..eee2726 --- /dev/null +++ b/apps/forum/templatetags/timesinceabbr.py @@ -0,0 +1,107 @@ +import calendar +import datetime + +from django.utils.html import avoid_wrapping +from django.utils.timezone import is_aware, utc +from django.utils.translation import gettext, ngettext_lazy + +from django import template +register = template.Library() + +TIME_STRINGS = { + 'year': ngettext_lazy('%d Y', '%d y'), + 'month': ngettext_lazy('%d M', '%d M'), + 'week': ngettext_lazy('%d W', '%d w'), + 'day': ngettext_lazy('%d d', '%d d'), + 'hour': ngettext_lazy('%d h', '%d h'), + 'minute': ngettext_lazy('%d m', '%d m'), +} + +TIMESINCE_CHUNKS = ( + (60 * 60 * 24 * 365, 'year'), + (60 * 60 * 24 * 30, 'month'), + (60 * 60 * 24 * 7, 'week'), + (60 * 60 * 24, 'day'), + (60 * 60, 'hour'), + (60, 'minute'), +) + + +def timesinceabbr(d, now=None, reversed=False, time_strings=None): + """ + Take two datetime objects and return the time between d and now as a nicely + formatted string, e.g. "10 minutes". If d occurs after now, return + "0 minutes". + + Units used are years, months, weeks, days, hours, and minutes. + Seconds and microseconds are ignored. Up to two adjacent units will be + displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are + possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not. + + `time_strings` is an optional dict of strings to replace the default + TIME_STRINGS dict. + + Adapted from + https://web.archive.org/web/20060617175230/http://blog.natbat.co.uk/archive/2003/Jun/14/time_since + """ + if time_strings is None: + time_strings = TIME_STRINGS + + # Convert datetime.date to datetime.datetime for comparison. + if not isinstance(d, datetime.datetime): + d = datetime.datetime(d.year, d.month, d.day) + if now and not isinstance(now, datetime.datetime): + now = datetime.datetime(now.year, now.month, now.day) + + now = now or datetime.datetime.now(utc if is_aware(d) else None) + + if reversed: + d, now = now, d + delta = now - d + + # Deal with leapyears by subtracing the number of leapdays + leapdays = calendar.leapdays(d.year, now.year) + if leapdays != 0: + if calendar.isleap(d.year): + leapdays -= 1 + elif calendar.isleap(now.year): + leapdays += 1 + delta -= datetime.timedelta(leapdays) + + # ignore microseconds + since = delta.days * 24 * 60 * 60 + delta.seconds + if since <= 0: + # d is in the future compared to now, stop processing. + return avoid_wrapping(gettext('0 minutes')) + for i, (seconds, name) in enumerate(TIMESINCE_CHUNKS): + count = since // seconds + if count != 0: + break + result = avoid_wrapping(time_strings[name] % count) + if i + 1 < len(TIMESINCE_CHUNKS): + # Now get the second item + seconds2, name2 = TIMESINCE_CHUNKS[i + 1] + count2 = (since - (seconds * count)) // seconds2 + if count2 != 0: + result += gettext(', ') + avoid_wrapping(time_strings[name2] % count2) + return result + + +def timeuntil(d, now=None, time_strings=None): + """ + Like timesince, but return a string measuring the time until the given time. + """ + return timesinceabbr(d, now, reversed=True, time_strings=time_strings) + + +@register.filter("timesinceabbr", is_safe=False) +def timesince_filter(value, arg=None): + """Format a date as the time since that date (i.e. "4 days, 6 hours").""" + if not value: + return '' + try: + if arg: + return timesinceabbr(value, arg) + return timesinceabbr(value) + except (ValueError, TypeError): + return '' diff --git a/apps/forum/urls.py b/apps/forum/urls.py index 79e2e0d..3cfd250 100644 --- a/apps/forum/urls.py +++ b/apps/forum/urls.py @@ -2,11 +2,13 @@ from django.urls import path from .views import ( TopicListView, + TopicDetailView, ) app_name = "forum" urlpatterns = [ - path(r't/', TopicListView.as_view(), name='topic-list',), - path(r'', TopicListView.as_view(), name='topic-redirect',), + path(r'', TopicListView.as_view(), name='topic-list',), + path(r'c/<str:slug>', TopicListView.as_view(), name='category-detail',), + path(r't/<str:slug>/<int:pk>', TopicDetailView.as_view(), name='topic-detail',), ] diff --git a/apps/forum/views.py b/apps/forum/views.py index bc7cc74..1540157 100644 --- a/apps/forum/views.py +++ b/apps/forum/views.py @@ -17,3 +17,17 @@ from utils.views import LoggedInViewWithUser class TopicListView(LoggedInViewWithUser, ListView): model = Topic + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['category_list'] = Category.objects.all() + return context + + +class TopicDetailView(LoggedInViewWithUser, DetailView): + model = Topic + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['category_list'] = Category.objects.all() + return context |