This commit is contained in:
2020-09-06 08:38:17 +00:00
20 changed files with 241 additions and 188 deletions

View File

@@ -17,11 +17,11 @@ from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf.urls.static import static from django.conf.urls.static import static
from django.conf import settings from django.conf import settings
from django.views.generic import RedirectView
from . import views from . import views
from posts.views import PostViewSet from posts.views import PostViewSet
from members.views import MemberViewSet from members.views import MemberViewSet
from rest_framework import routers from rest_framework import routers
# from authentications.decorators import authenticated_user
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'posts', PostViewSet) router.register(r'posts', PostViewSet)
@@ -30,6 +30,7 @@ router.register(r'members', MemberViewSet)
urlpatterns = [ urlpatterns = [
path('posts/', include('posts.urls')), path('posts/', include('posts.urls')),
path('admin/doc/', include('django.contrib.admindocs.urls')), path('admin/doc/', include('django.contrib.admindocs.urls')),
path('admin/login/', RedirectView.as_view(pattern_name='login')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('auth/', include('authentications.urls')), path('auth/', include('authentications.urls')),
path('', views.index, name='home'), path('', views.index, name='home'),

View File

@@ -5,7 +5,7 @@ from posts.models import Post, FetMeeting, Event
def index(request): def index(request):
posts = deque(Post.article_objects.all()) posts = deque(Post.articles.get_visible_articles())
def get_tags(lst): def get_tags(lst):
for p in lst: for p in lst:
@@ -13,16 +13,24 @@ def index(request):
yield "#" + t yield "#" + t
t = set(t for t in get_tags(posts)) t = set(t for t in get_tags(posts))
if len(posts) >= 1:
featured_post = posts.popleft() # set the pinned post
featured_post = Post.articles.get_pinned_article()
if not featured_post:
# if a pinned post does not exist, take the last published one.
if len(posts) >= 1:
featured_post = posts.popleft()
else:
featured_post = 0
else: else:
featured_post = 0 # remove the pinned post
posts.remove(featured_post)
context = { context = {
'posts': posts, 'posts': posts,
'events': Event.objects.get_five_events(), 'events': Event.all_events.get_five_events(),
'featured_post': featured_post, 'featured_post': featured_post,
'featured_post2': FetMeeting.objects.first(), 'featured_meeting': FetMeeting.objects.get_meetings(),
'tags_list': ", ".join(t) 'tags_list': ", ".join(t)
} }

View File

@@ -8,6 +8,5 @@ urlpatterns = [
path('<str:filter>', views.members_view), path('<str:filter>', views.members_view),
path('jobs/<str:slug>', views.jobs_view), path('jobs/<str:slug>', views.jobs_view),
path('job/<str:slug>', views.job_view),
path('member/<str:member_name>', views.profile_view, name="member"), path('member/<str:member_name>', views.profile_view, name="member"),
] ]

View File

@@ -1,9 +1,8 @@
from django.shortcuts import render from django.shortcuts import render
# from django.http import HttpResponse
from collections import deque from collections import deque
from .models import Member, JobMember, JobGroup, MemberSerializer, Job from .models import Member, JobMember, JobGroup, MemberSerializer
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework import permissions from rest_framework import permissions
@@ -47,24 +46,6 @@ def jobs_view(request, slug=None):
return render(request, 'members/index.html', context) return render(request, 'members/index.html', context)
def job_view(request, slug=None):
job_group = deque(JobGroup.objects.all())
job_list = []
job = Job.objects.get(slug=slug)
job_names = [job.name]
active_members = JobMember.active_member.get_members_of_job(job_names=job_names)
inactive_members = JobMember.inactive_member.get_members_of_job(job_names=job_names)
for idx, item in enumerate(job_names):
job_list.append((job_names[idx], active_members[idx], inactive_members[idx]))
context = {
"job_group": job_group,
"job_list": job_list,
}
return render(request, 'members/index.html', context)
def members_view(request, filter=None): def members_view(request, filter=None):
job_group = deque(JobGroup.objects.all()) job_group = deque(JobGroup.objects.all())
@@ -86,12 +67,15 @@ def members_view(request, filter=None):
def profile_view(request, member_name=None): def profile_view(request, member_name=None):
job_group = deque(JobGroup.objects.all()) job_group = deque(JobGroup.objects.all())
member = None member = None
jobs = None
member = deque(Member.all_members.filter(nickname=member_name)) member = deque(Member.all_members.filter(nickname=member_name))
jobs = deque(JobMember.members.filter(member__nickname=member_name))
context = { context = {
"job_group": job_group, "job_group": job_group,
"member": member, "member": member,
"jobs": jobs,
} }
return render(request, 'members/index.html', context) return render(request, 'members/index.html', context)

View File

@@ -22,8 +22,9 @@ make_fetmeeting.short_description = "In eine Fachschaftssitzung konvertieren"
class MyPostAdmin(admin.ModelAdmin): class MyPostAdmin(admin.ModelAdmin):
form = MyPostForm form = MyPostForm
model = Post model = Post
list_filter = ['is_event'] list_filter = ['is_pinned', 'is_hidden']
list_display = ['title', 'subtitle', 'slug', 'public_date'] list_display = ['title', 'subtitle', 'slug', 'public_date', 'is_pinned', 'is_hidden']
ordering = ['is_hidden', '-public_date']
def add_view(self, request, form_url='', extra_context=None): def add_view(self, request, form_url='', extra_context=None):
extra_context = extra_context or {} extra_context = extra_context or {}
@@ -59,7 +60,8 @@ class MyPostAdmin(admin.ModelAdmin):
class MyEventAdmin(MyPostAdmin): class MyEventAdmin(MyPostAdmin):
form = MyEventForm form = MyEventForm
model = Event model = Event
list_display = ['title', 'subtitle', 'slug', 'event_start', 'public_date'] list_display = ['title', 'subtitle', 'slug', 'event_start', 'public_date', 'is_pinned']
ordering = ['-event_start']
actions = [make_fetmeeting] actions = [make_fetmeeting]
@@ -77,6 +79,8 @@ admin.site.register(News, MyNewsAdmin)
class MyFetMeetingAdmin(MyEventAdmin): class MyFetMeetingAdmin(MyEventAdmin):
form = MyFetMeetingForm form = MyFetMeetingForm
model = FetMeeting model = FetMeeting
list_filter = []
list_display = ['title', 'slug', 'event_start', 'public_date']
admin.site.register(FetMeeting, MyFetMeetingAdmin) admin.site.register(FetMeeting, MyFetMeetingAdmin)

View File

@@ -21,7 +21,10 @@ class MyPostForm(forms.ModelForm):
class MyNewsForm(MyPostForm): class MyNewsForm(MyPostForm):
class Meta: class Meta:
model = News model = News
fields = ['title', 'subtitle', 'tags', 'image', 'body', 'slug', 'author', 'public_date'] fields = [
'title', 'subtitle', 'tags', 'image', 'body', 'slug', 'author', 'public_date',
'is_pinned', 'is_hidden',
]
widgets = {'body': CKEditorUploadingWidget(config_name='default')} widgets = {'body': CKEditorUploadingWidget(config_name='default')}
@@ -34,7 +37,7 @@ class MyEventForm(MyPostForm):
model = Event model = Event
fields = [ fields = [
'title', 'subtitle', 'tags', 'image', 'body', 'event_start', 'event_end', 'title', 'subtitle', 'tags', 'image', 'body', 'event_start', 'event_end',
'event_place', 'slug', 'author', 'public_date', 'event_place', 'slug', 'author', 'public_date', 'is_pinned',
] ]
widgets = {'body': CKEditorUploadingWidget(config_name='default')} widgets = {'body': CKEditorUploadingWidget(config_name='default')}

82
fet2020/posts/managers.py Normal file
View File

@@ -0,0 +1,82 @@
from django.db import models
from django.db.models import Q
from django.utils import timezone
class PostManager(models.Manager):
def get_queryset(self):
return super().get_queryset()
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
class ArticleManager(models.Manager):
"""
Provide a query set only for "Article"
regular fet meetings should not be contained in the news stream
"""
def get_queryset(self):
return super().get_queryset().filter(
Q(post_type='E')
| Q(post_type='N')
).order_by('-public_date')
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
def get_pinned_article(self):
return self.get_visible_articles().filter(is_pinned=True).first()
class NewsManager(models.Manager):
"""
Provide a query set only for "News"
"""
def get_queryset(self):
return super().get_queryset().filter(post_type='N')
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
class AllEventManager(models.Manager):
"""
Provide a query set for all events ("Event" and "Fet Meeting")
"""
def get_queryset(self):
return super().get_queryset().filter(Q(post_type='E') | Q(post_type='F'))
def get_five_events(self):
return self.get_queryset().order_by('-event_start')[:5]
class EventManager(models.Manager):
"""
Provide a query set only for "Events"
regular fet meetings should not be contained in the news stream
"""
def get_queryset(self):
return super().get_queryset().filter(post_type='E')
class FetMeetingManager(models.Manager):
"""
Provide a query set only for "Fet Meeting"
"""
def get_queryset(self):
return super().get_queryset().filter(post_type='F')
def _get_future_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__gt=date_today).order_by('event_start')
def _get_past_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__lt=date_today).order_by('-event_start')
def get_meetings(self):
meetings = []
meetings.append(self._get_future_events().first())
meetings.append(self._get_past_events().first())
return meetings

View File

@@ -1,16 +1,21 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.validators import ValidationError from django.core.validators import ValidationError
from django.db import models from django.db import models
from django.db.models import Q
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from members.models import Member
from taggit.managers import TaggableManager from taggit.managers import TaggableManager
# import documents # import documents
from documents import ep from documents import ep
from .managers import (
PostManager, ArticleManager, NewsManager, AllEventManager, EventManager, FetMeetingManager
)
# from ckeditor_uploader import RichTextUploadingField # from ckeditor_uploader import RichTextUploadingField
# import uuid # import uuid
import re import re
@@ -22,65 +27,6 @@ import logging
logger = logging.getLogger('posts') logger = logging.getLogger('posts')
############
# MANAGERS #
############
class PostManager(models.Manager):
def get_queryset(self):
return super().get_queryset()
class ArticleManager(models.Manager):
"""
Provide a query set only for "Article"
regular fet meetings should not be contained in the news stream
"""
def get_queryset(self):
return super().get_queryset().filter(
Q(post_type='E')
| Q(post_type='N')
).order_by('-public_date')
class NewsManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(~Q(is_event=True))
class EventManager(models.Manager):
"""
Provide a query set only for "Events"
regular fet meetings should not be contained in the news stream
"""
def get_queryset(self):
return super().get_queryset().filter(
Q(is_event=True)
& ~Q(post_type='F')
).order_by('-public_date')
def get_all_events(self):
date_today = timezone.now().date()
return super().get_queryset().filter(
Q(is_event=True)
& Q(event_start__gt=date_today)
).order_by('-event_start')
def get_five_events(self):
return super().get_queryset().filter(
Q(is_event=True)
).order_by('-event_start')[:5]
class FetMeetingManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(Q(post_type='F'))
##########
# MODELS #
##########
class Category(models.Model): class Category(models.Model):
# Titel des Posts # Titel des Posts
title = models.CharField(max_length=200) title = models.CharField(max_length=200)
@@ -128,7 +74,11 @@ class Post(models.Model):
] ]
post_type = models.CharField(max_length=1, choices=__choices, editable=False) post_type = models.CharField(max_length=1, choices=__choices, editable=False)
is_event = models.BooleanField(default=False) # post is pinned at main page
is_pinned = models.BooleanField(default=False)
# post is hidden from newsfeed (e.g. about)
is_hidden = models.BooleanField(default=False)
# Zusatz Info wenn ein Event gepostet wird # Zusatz Info wenn ein Event gepostet wird
event_start = models.DateTimeField('Event Start', null=True, blank=True) event_start = models.DateTimeField('Event Start', null=True, blank=True)
@@ -147,7 +97,7 @@ class Post(models.Model):
# Managers # Managers
objects = PostManager() objects = PostManager()
article_objects = ArticleManager() articles = ArticleManager()
def get_tags(self): def get_tags(self):
"""Returns assigned tags as a comma seperated list.""" """Returns assigned tags as a comma seperated list."""
@@ -191,10 +141,6 @@ class Post(models.Model):
def url(self): def url(self):
return reverse('posts.show', kwargs={"id": self.slug}) return reverse('posts.show', kwargs={"id": self.slug})
@property
def author_member(self):
return Member.all_members.filter(nickname=self.author.username).first()
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"save the post with some defaults" "save the post with some defaults"
if (self.id is None) and (not self.slug): if (self.id is None) and (not self.slug):
@@ -253,7 +199,8 @@ class News(Post):
class Event(Post): class Event(Post):
objects = EventManager() only_events = EventManager()
all_events = AllEventManager()
class Meta: class Meta:
proxy = True proxy = True
@@ -276,8 +223,6 @@ class Event(Post):
raise ValidationError(_('Das Ende des Events liegt vor dem Beginn.')) raise ValidationError(_('Das Ende des Events liegt vor dem Beginn.'))
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.is_event = True
if not self.post_type: if not self.post_type:
self.post_type = 'E' self.post_type = 'E'
@@ -296,12 +241,15 @@ class FetMeeting(Event):
def clean(self): def clean(self):
if self.event_start is None: if self.event_start is None:
raise ValidationError(_('Das Datum des Events fehlt.')) raise ValidationError(_('Das Datum des Events fehlt.'))
elif (self.event_end) and (self.event_end < self.event_start):
raise ValidationError(_('Das Ende des Events liegt vor dem Beginn.'))
slug = slugify(self.event_start.date()) + "-" + slugify("Fachschaftssitzung") slug = slugify(self.event_start.date()) + "-" + slugify("Fachschaftssitzung")
#dieser Check verhindert erneutes speichern
#if Post.objects.filter(slug=slug).count() != 0: if Post.objects.filter(slug=slug).exists():
# raise ValidationError(_('Es existiert bereits eine Sitzung mit demselben Datum.')) if Post.objects.get(slug=slug).id != self.id:
raise ValidationError(_('Es existiert bereits eine Sitzung mit demselben Datum.'))
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.title = "Fachschaftssitzung" self.title = "Fachschaftssitzung"

View File

@@ -9,8 +9,8 @@ from taggit.models import Tag
from rest_framework import viewsets from rest_framework import viewsets
# from rest_framework import permissions # from rest_framework import permissions
from .models import Post, PostSerializer from .models import Post, PostSerializer, FetMeeting
# from members.models import Member from members.models import Member
# from documents import add_ep_to_response, get_ep_sessionid2 # from documents import add_ep_to_response, get_ep_sessionid2
from documents import get_pad_link from documents import get_pad_link
from documents.etherpadlib import add_ep_cookie from documents.etherpadlib import add_ep_cookie
@@ -23,7 +23,7 @@ from collections import deque
################## ##################
def index(request): def index(request):
posts = deque(Post.objects.order_by('-public_date').all()) posts = deque(Post.objects.get_visible_articles().order_by('-public_date'))
def f(p): def f(p):
return p.tags return p.tags
@@ -33,13 +33,15 @@ def index(request):
def tags(request, tag=""): def tags(request, tag=""):
posts = deque(Post.objects.filter(tags__name=tag)) posts = deque(Post.objects.get_visible_articles().filter(tags__name=tag))
featured_post = Post.objects.filter(slug=tag).first() featured_post = Post.objects.get_visible_articles().filter(slug=tag).first()
context = { context = {
"posts": posts, "posts": posts,
"featured_post": featured_post, "featured_post": featured_post,
"tags_list": None, "tags_list": None,
} }
return render(request, 'posts/tag.html', context) return render(request, 'posts/tag.html', context)
@@ -49,14 +51,18 @@ def show(request, id=None):
elif id != "" and id is not None: elif id != "" and id is not None:
p = Post.objects.get(slug=(id)) p = Post.objects.get(slug=(id))
# post_author = Member.all_members.filter(nickname=p.author) post_author = Member.all_members.filter(nickname=p.author).first()
author_image = None
if post_author:
author_image = post_author.image['avatar'].url
context = { context = {
"post": p, "post": p,
"next": get_next_dict().get(p.slug, None), "author_image": author_image,
"next": get_next_dict(p),
"related_posts": p.tags.similar_objects(), "related_posts": p.tags.similar_objects(),
"ep_link": get_pad_link(p.slug + "-agenda"), "ep_link": get_pad_link(p.slug + "-agenda"),
} }
response = render(request, 'posts/show.html', context) response = render(request, 'posts/show.html', context)
@@ -106,17 +112,27 @@ def tag_complete(request):
return HttpResponseServerError("Requires a term field.") return HttpResponseServerError("Requires a term field.")
def get_next_dict(): def get_next_dict(post=None):
# TODO: Docstring # TODO: Docstring
posts = Post.article_objects.order_by('-public_date').values('slug') posts = None
print(posts) d = post.slug
d = {}
print(d) if post:
for k, v in enumerate(posts): # TODO: bad implementation but it works!!
if k == len(posts) - 1: if post.post_type == 'N' or post.post_type == 'E':
break posts = Post.articles.get_visible_articles()
d[v['slug']] = posts[k + 1]['slug'] elif post.post_type == 'F':
print(d) posts = FetMeeting.objects.get_queryset().order_by('-event_start')
if posts:
for k, v in enumerate(posts):
if post.slug == v.slug:
if (k + 1) < len(posts):
d = posts[k + 1].slug
else:
d = posts[0].slug
break
return d return d

View File

@@ -1,9 +1,9 @@
django django==3.1.*
django-taggit django-taggit==1.3.0
django-ckeditor django-ckeditor==5.9.0
Pillow Pillow==7.2.0
djangorestframework djangorestframework==3.11.0
django-static-jquery-ui django-static-jquery-ui==1.12.1.1
docutils docutils==0.16
easy-thumbnails easy-thumbnails==2.7.0
etherpad-lite etherpad-lite==0.5

View File

@@ -34,9 +34,9 @@
{% with post=featured_post %} {% with post=featured_post %}
{% include 'posts/partials/_article_row.html' %} {% include 'posts/partials/_article_row.html' %}
{% endwith %} {% endwith %}
{% with post=featured_post2 %} {% for post in featured_meeting %}
{% include 'posts/partials/_article_row.html' %} {% include 'posts/partials/_meeting_row.html' %}
{% endwith %} {% endfor %}
</div> </div>
</div> </div>

View File

@@ -1,3 +1,4 @@
{% if active_members %} {% if active_members %}
<b>Aktuelle Mitglieder:</b> <b>Aktuelle Mitglieder:</b>
{% with job_memberships=active_members %} {% with job_memberships=active_members %}

View File

@@ -1,18 +1,11 @@
<div class="grid-container"> <div class="grid-container">
<h2> Grid Style</h2>
<div class="grid-x"> <div class="grid-x">
{% for member in members %} {% for member in members %}
<div class="medium-3 large-2 small-6 cell"> <div class="medium-3 large-2 small-6 cell">
<h2>{{member.surname}}</h2>
{% include 'members/partials/_member.html' %} {% include 'members/partials/_member.html' %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
<h2> Grid Style 2</h2>
<div class="grid-x">
{% for member in members %}
{% include 'members/partials/_member.html' %}
{% endfor %}
</div>
</div> </div>

View File

@@ -1,8 +1,10 @@
<div class="grid-x"> <div class="grid-x">
{% for mem in job_memberships %} {% for mem in job_memberships %}
{% with member=mem.member %} {% with member=mem.member %}
<div class="medium-3 large-2 small-6 cell">{{mem.get_job_role_display}} (seit {{mem.job_start}}) <div class="medium-3 large-2 small-6 cell">
<h2>{{mem.member.surname}}</h2>
{% include 'members/partials/_member.html' %} {% include 'members/partials/_member.html' %}
<h2>{{mem.get_job_role_display}} ({{mem.job_start}} - {{mem.job_end}})</h2>
</div> </div>
{%endwith %} {%endwith %}
{% endfor %} {% endfor %}

View File

@@ -1,8 +1,10 @@
{# only thumb and name of member #} {# only thumb and name of member #}
{% load thumbnail %}
<a class="thumbnail member-thumb" href="/members/member/{{member.nickname}}" style="width:150px;height:150px"> <a class="thumbnail member-thumb" href="/members/member/{{member.nickname}}" style="width:150px;height:150px">
<img src="{{member.image.thumb.url}}" alt="" /> <img src="{{member.image.thumb.url}}" alt="" />
<div class="thumb-layer"><div><h1>{{member.nickname}}</h1> <p>{{member.firstname}} {{member.surname}}</p></div></div> <div class="thumb-layer">
<div>
<h1>{{member.nickname}}</h1>
<p>{{member.firstname}} {{member.surname}}</p>
</div>
</div>
</a> </a>

View File

@@ -1,19 +1,20 @@
{# This template shows one member and all the details (that are ment for public) including a list of current jobs #} {# This template shows one member and all the details (that are ment for public) including a list of current jobs #}
{% load thumbnail %}
<div class="media-object"> <div class="media-object">
<div class="media-object-section"> <div class="media-object-section">
<div class="thumbnail"> <div class="thumbnail">
<img src= "{{member.image.url}}" style="width:150px;"> <img src= "{{member.image.url}}" style="width:150px;">
</div>
</div>
<div class="media-object-section main-section">
<h1>{{member.firstname}} {{member.surname}}</h1>
<p>Spitzname: {{member.nickname}} </br>
Name: {{member.firstname}} {{member.surname}} </br>
Mailaccount: {{member.mailaccount}} </br>
Beschreibung: {{member.description|safe}} </br>
</p>
ehrenamtliche Tätigkeiten </br>
{% for jobm in jobs %}
{{jobm.job.name}}: {{jobm.job_start|date}} - {{jobm.job_end|date}} </br>
{% endfor %}
</div> </div>
</div>
<div class="media-object-section main-section">
<h1>{{member.firstname}} {{member.surname}}</h1>
<p>Spitzname: {{member.nickname}} </br>
Name: {{member.firstname}} {{member.surname}} </br>
Mailaccount: {{member.mailaccount}} </br>
Beschreibung: {{member.description|safe}} </br>
</p>
</div>
</div> </div>

View File

@@ -1,15 +1,12 @@
<a href="{{post.url}}"> <a href="{{post.url}}">
<article class="article-row">
<article class="article-row">
<div class="article-row-content"> <div class="article-row-content">
<h1 class="article-row-content-header">{{post.title}}</h1> <h1 class="article-row-content-header">{{post.title}}</h1>
{% if post.subtitle is not None %}
<p class="article-row-content-description">{{post.subtitle}}</p> <p class="article-row-content-description">{{post.subtitle}}</p>
{% endif %}
<p class="article-row-content-author">{{post.author}}</p> <p class="article-row-content-author">{{post.author}}</p>
<time class="article-row-content-time" datetime="2008-02-14 20:00">{{post.public_date}}</time> <time class="article-row-content-time" datetime="2008-02-14 20:00">{{post.public_date}}</time>
</div> </div>
</article> </article>
</a>
</a>

View File

@@ -1,10 +1,11 @@
<a href ="posts/{{post.slug}}"> <a href ="posts/{{post.slug}}">
<div class="date-box"> <div class="date-box">
<span> <span>
<span class="date-badge badge primary" style=""> <span class="date-badge badge primary" style="">
<span class="date-badge-day">{{post.event_start_day}}</span> <span class="date-badge-day">{{post.event_start_day}}</span>
<span class="date-badge-month">{{post.event_start_month}}</span> <span class="date-badge-month">{{post.event_start_month}}</span>
</span></span> </span>
</span>
<span class="date-text"><strong>{{post.title}}</strong></span> <span class="date-text"><strong>{{post.title}}</strong></span>
</div>
</div></a> </a>

View File

@@ -0,0 +1,11 @@
<a href="{{post.url}}">
<article class="article-row">
<div class="article-row-content">
<h1 class="article-row-content-header">{{post.title}}</h1>
{% if post.subtitle is not None %}
<p class="article-row-content-description">{{post.subtitle}}</p>
{% endif %}
<time class="article-row-content-time" datetime="2008-02-14 20:00">{{post.event_start}}</time>
</div>
</article>
</a>

View File

@@ -15,9 +15,9 @@
</div> </div>
<div class="article-details"> <div class="article-details">
{{post.subtitle | tags_to_url }} {{post.subtitle | tags_to_url }}
{% if post.author_member != None %} {% if post.author != None %}
<div class="article-author"><a href="{% url 'member' post.author_member.nickname %}"> <div class="article-author"><a href="{% url 'member' post.author %}">
<img src="{{post.author_member.image | thumbnail_url:'avatar'}}" alt="" />{{post.author_member.nickname}} <img src="{{author_image}}" alt="" /> {{post.author}}
</a> </a>
</div> </div>
{% else %} {% else %}