add post status and delete is_hidden

This commit is contained in:
2022-01-12 22:44:00 +00:00
parent 94afc0259b
commit 8c8a3d378a
8 changed files with 164 additions and 154 deletions

View File

@@ -6,7 +6,7 @@ from posts.models import Post, FetMeeting, Event
def index(request): def index(request):
posts = deque(Post.articles.get_date_sorted_list()) posts = deque(Post.articles.date_sorted_list())
posts_for_tags = deque(Post.objects.get_last_months_posts()) posts_for_tags = deque(Post.objects.get_last_months_posts())
def get_tags(lst): def get_tags(lst):
@@ -17,28 +17,28 @@ def index(request):
t = set(t for t in get_tags(posts_for_tags)) t = set(t for t in get_tags(posts_for_tags))
# set the pinned post # set the pinned post
featured_post = Post.articles.get_pinned_article() pinned_post = Post.articles.pinned()
if not featured_post: if not pinned_post:
# if a pinned post does not exist, take the last published one. # if a pinned post does not exist, take the last published one.
if len(posts) >= 1: if len(posts) >= 1:
featured_post = posts.popleft() pinned_post = posts.popleft()
else:
featured_post = 0
else: else:
# remove the pinned post # remove the pinned post
posts.remove(featured_post) posts.remove(pinned_post)
featured_event = Event.only_events.get_future_events().first() featured_event = Event.only_events.future_events().first()
# if there is no futurity event # if there is no futurity event
if not featured_event: if not featured_event:
featured_event = Event.only_events.get_past_events().first() featured_event = Event.only_events.past_events().first()
featured_meeting = FetMeeting.objects.get_meetings() featured_meeting = deque([])
featured_meeting.append(FetMeeting.objects.future_events().first())
featured_meeting.append(FetMeeting.objects.past_events().first())
context = { context = {
"posts": deque(list(posts)[:5]), "posts": deque(list(posts)[:5]),
"events": Event.all_events.get_five_events(), "events": Event.all_events.future_events()[:5],
"featured_post": featured_post, "featured_post": pinned_post,
"featured_event": featured_event, "featured_event": featured_event,
"featured_meeting": featured_meeting, "featured_meeting": featured_meeting,
"tags_list": " ".join(t), "tags_list": " ".join(t),

View File

@@ -55,9 +55,9 @@ class FileUploadInline(admin.TabularInline):
class PostAdmin(admin.ModelAdmin): class PostAdmin(admin.ModelAdmin):
form = PostForm form = PostForm
model = Post model = Post
list_filter = ["is_pinned", "is_hidden"] list_filter = ["is_pinned", "status"]
list_display = ["title", "slug", "public_date", "is_pinned", "is_hidden"] list_display = ["title", "slug", "public_date", "status", "is_pinned"]
ordering = ["is_hidden", "-public_date"] ordering = ["-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 {}
@@ -104,8 +104,8 @@ class NewsAdmin(PostAdmin):
class EventAdmin(PostAdmin): class EventAdmin(PostAdmin):
form = EventForm form = EventForm
model = Event model = Event
list_filter = ["is_pinned"] list_filter = ["is_pinned", "status"]
list_display = ["title", "slug", "event_start", "public_date", "is_pinned"] list_display = ["title", "slug", "event_start", "status", "is_pinned"]
ordering = ["-event_start"] ordering = ["-event_start"]
actions = [make_fetmeeting] actions = [make_fetmeeting]
@@ -114,7 +114,7 @@ class FetMeetingAdmin(EventAdmin):
form = FetMeetingForm form = FetMeetingForm
model = FetMeeting model = FetMeeting
list_filter = [] list_filter = []
list_display = ["title", "slug", "event_start", "public_date"] list_display = ["title", "slug", "event_start"]
actions = [] actions = []

View File

@@ -39,13 +39,13 @@ class NewsForm(PostForm):
"title", "title",
"subtitle", "subtitle",
"tags", "tags",
"status",
"image", "image",
"body", "body",
"slug", "slug",
"author", "author",
"public_date", "public_date",
"is_pinned", "is_pinned",
"is_hidden",
] ]
labels = { labels = {
@@ -57,7 +57,6 @@ class NewsForm(PostForm):
"author": _("Autor"), "author": _("Autor"),
"public_date": _("Veröffentlichung"), "public_date": _("Veröffentlichung"),
"is_pinned": _("Post anheften"), "is_pinned": _("Post anheften"),
"is_hidden": _("Post verstecken"),
} }
help_texts = { help_texts = {
@@ -68,9 +67,6 @@ class NewsForm(PostForm):
"is_pinned": _( "is_pinned": _(
"Dieser Post soll an die Startseite als erster Post angeheftet werden." "Dieser Post soll an die Startseite als erster Post angeheftet werden."
), ),
"is_hidden": _(
"Dieser Post soll im News Feed nicht auftauchen, z.B. Impressum."
),
} }
widgets = {"body": CKEditorUploadingWidget(config_name="default")} widgets = {"body": CKEditorUploadingWidget(config_name="default")}
@@ -89,6 +85,7 @@ class EventForm(PostForm):
"title", "title",
"subtitle", "subtitle",
"tags", "tags",
"status",
"image", "image",
"body", "body",
"event_start", "event_start",

View File

@@ -1,20 +1,26 @@
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q, Manager
from django.utils import timezone from django.utils import timezone
from datetime import timedelta from datetime import timedelta
class PostManager(models.Manager): class PublishedManager(Manager):
def published(self, public=True):
if public:
qs = self.get_queryset().filter(status="20")
else:
qs = self.get_queryset()
return qs
class PostManager(PublishedManager, Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().order_by("-public_date") return super().get_queryset().order_by("-public_date")
def get_visible_articles(self): def date_sorted_list(self, public=True):
return self.get_queryset().filter(is_hidden=False)
def get_date_sorted_list(self):
post_list = [] post_list = []
for post in self.get_visible_articles(): for post in self.published(public):
if post.post_type != "N": if post.post_type != "N":
post_list.append((post, post.event_start.date())) post_list.append((post, post.event_start.date()))
else: else:
@@ -25,13 +31,20 @@ class PostManager(models.Manager):
return posts return posts
def get_date_filtered_list(self, year=None, month=None, fet_meeting_only=None): def date_filtered_list(
self,
public=True,
year=None,
month=None,
fet_meeting_only=None,
):
post_list = [] post_list = []
qs = self.published(public)
if not fet_meeting_only: if not fet_meeting_only:
posts = self.get_visible_articles().filter(~Q(post_type="N")) posts = qs.filter(~Q(post_type="N"))
else: else:
posts = self.get_visible_articles().filter(post_type="F") posts = qs.filter(post_type="F")
if year: if year:
posts = posts.filter(event_start__year=year) posts = posts.filter(event_start__year=year)
@@ -42,7 +55,7 @@ class PostManager(models.Manager):
post_list.append((post, post.event_start.date())) post_list.append((post, post.event_start.date()))
if not fet_meeting_only: if not fet_meeting_only:
posts = self.get_visible_articles().filter(post_type="N") posts = qs.filter(post_type="N")
if year: if year:
posts = posts.filter(public_date__year=year) posts = posts.filter(public_date__year=year)
@@ -57,40 +70,27 @@ class PostManager(models.Manager):
return posts return posts
def get_last_months_posts(self): # use for finding tags at homepage - TODO: delete when new design published
def get_last_months_posts(self, public=True):
date_today = timezone.now().date() date_today = timezone.now().date()
return self.get_visible_articles().filter( return self.published(public).filter(
public_date__gt=date_today - timedelta(days=365) public_date__gt=date_today - timedelta(days=365)
) )
def get_all_posts_with_date(self):
return (
self.get_queryset()
.filter(Q(event_start__isnull=False) & Q(event_end__isnull=False))
.order_by("-event_start")
)
class ArticleManager(PublishedManager, Manager):
class ArticleManager(models.Manager):
""" """
Provide a query set only for "Article" Provide a query set only for "Article"
regular fet meetings should not be contained in the news stream regular fet meetings should not be contained in the news stream
""" """
def get_queryset(self): def get_queryset(self):
return ( qs = super().get_queryset().filter(Q(post_type="E") | Q(post_type="N"))
super() return qs.order_by("-public_date")
.get_queryset()
.filter(Q(post_type="E") | Q(post_type="N"))
.order_by("-public_date")
)
def get_visible_articles(self): def date_sorted_list(self, public=True):
return self.get_queryset().filter(is_hidden=False)
def get_date_sorted_list(self):
post_list = [] post_list = []
for post in self.get_visible_articles(): for post in self.published(public):
if post.post_type != "N": if post.post_type != "N":
post_list.append((post, post.event_start.date())) post_list.append((post, post.event_start.date()))
else: else:
@@ -101,11 +101,11 @@ class ArticleManager(models.Manager):
return posts return posts
def get_pinned_article(self): def pinned(self, public=True):
return self.get_visible_articles().filter(is_pinned=True).first() return self.published(public).filter(is_pinned=True).first()
class NewsManager(models.Manager): class NewsManager(PublishedManager, Manager):
""" """
Provide a query set only for "News" Provide a query set only for "News"
""" """
@@ -113,79 +113,60 @@ class NewsManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(post_type="N").order_by("-public_date") return super().get_queryset().filter(post_type="N").order_by("-public_date")
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
class AllEventManager(PublishedManager, Manager):
class AllEventManager(models.Manager):
""" """
Provide a query set for all events ("Event" and "Fet Meeting") Provide a query set for all events ("Event" and "Fet Meeting")
""" """
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(Q(post_type="E") | Q(post_type="F"))
def get_five_events(self):
date_today = timezone.now()
return ( return (
self.get_queryset() super()
.filter(event_start__gt=date_today) .get_queryset()
.order_by("event_start")[:5] .filter(Q(post_type="E") | Q(post_type="F"))
.order_by("-event_start")
) )
def future_events(self, public=True):
date_today = timezone.now()
qs = self.published(public).filter(event_start__gt=date_today)
return qs.reverse()
class EventManager(models.Manager):
class EventManager(PublishedManager, Manager):
""" """
Provide a query set only for "Events" Provide a query set only for "Events"
regular fet meetings should not be contained in the news stream regular fet meetings should not be contained in the news stream
""" """
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(post_type="E") return super().get_queryset().filter(post_type="E").order_by("-event_start")
def get_future_events(self): def future_events(self, public=True):
date_today = timezone.now() date_today = timezone.now()
return ( qs = self.published(public).filter(event_start__gt=date_today)
self.get_queryset() return qs.reverse()
.filter(event_start__gt=date_today)
.order_by("event_start")
)
def get_past_events(self): def past_events(self, public=True):
date_today = timezone.now() date_today = timezone.now()
return ( qs = self.published(public).filter(event_start__lt=date_today)
self.get_queryset() return qs
.filter(event_start__lt=date_today)
.order_by("-event_start")
)
class FetMeetingManager(models.Manager): class FetMeetingManager(PublishedManager, Manager):
""" """
Provide a query set only for "Fet Meeting" Provide a query set only for "Fet Meeting"
""" """
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(post_type="F") return super().get_queryset().filter(post_type="F").order_by("-event_start")
def _get_future_events(self): def future_events(self):
date_today = timezone.now() date_today = timezone.now()
return ( qs = self.published().filter(event_start__gt=date_today)
self.get_queryset() return qs.reverse()
.filter(event_start__gt=date_today)
.order_by("event_start")
)
def _get_past_events(self): def past_events(self):
date_today = timezone.now() date_today = timezone.now()
return ( qs = self.published().filter(event_start__lt=date_today)
self.get_queryset() return qs
.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

@@ -88,12 +88,21 @@ class Post(models.Model):
__choices = [("N", _("News")), ("E", _("Event")), ("F", _("FetMeeting"))] __choices = [("N", _("News")), ("E", _("Event")), ("F", _("FetMeeting"))]
post_type = models.CharField(max_length=1, choices=__choices, editable=True) post_type = models.CharField(max_length=1, choices=__choices, editable=True)
class Status(models.TextChoices):
DRAFT = "10", _("DRAFT")
ONLY_INTERN = "15", _("ONLY_INTERN")
PUBLIC = "20", _("PUBLIC")
status = models.CharField(
verbose_name="Status",
max_length=2,
choices=Status.choices,
default=Status.DRAFT,
)
# post is pinned at main page # post is pinned at main page
is_pinned = models.BooleanField(verbose_name="ANGEHEFTET", default=False) is_pinned = models.BooleanField(verbose_name="ANGEHEFTET", default=False)
# post is hidden from newsfeed (e.g. about)
is_hidden = models.BooleanField(verbose_name="UNSICHTBAR", default=False)
# addional infos for events # addional infos for events
event_start = models.DateTimeField( event_start = models.DateTimeField(
verbose_name="Event Start", null=True, blank=True verbose_name="Event Start", null=True, blank=True
@@ -263,6 +272,13 @@ class Post(models.Model):
) )
super().clean() super().clean()
@property
def published(self):
if self.status == self.Status.PUBLIC:
return True
return False
class News(Post): class News(Post):
objects = NewsManager() objects = NewsManager()
@@ -342,6 +358,9 @@ class FetMeeting(Event):
if not self.event_end: if not self.event_end:
self.event_end = self.event_start + timedelta(hours=2) self.event_end = self.event_start + timedelta(hours=2)
# set FET Meeting always public
self.status = self.Status.PUBLIC
super().save(*args, **kwargs) super().save(*args, **kwargs)
def __get_slug(self): def __get_slug(self):

View File

@@ -23,7 +23,6 @@ class PostSerializer(serializers.HyperlinkedModelSerializer):
"image", "image",
"event_start", "event_start",
"event_end", "event_end",
"is_hidden",
"agenda_html", "agenda_html",
"protocol_html", "protocol_html",
"has_agenda", "has_agenda",

View File

@@ -7,18 +7,20 @@ from .utils import slug_calc, tag_complete
app_name = apps.PostsConfig.name app_name = apps.PostsConfig.name
urlpatterns = [ urlpatterns = [
path("func/tag_complete", tag_complete),
path("func/slug_calc", slug_calc),
path("t/<str:tag>", views.tags, name="posts.tags"),
path("", views.index, name="posts.index"), path("", views.index, name="posts.index"),
path("fet_calendar.ics", views.calendar, name="posts.calendar"),
path("<str:id>", views.show, name="posts.show"), path("<str:id>", views.show, name="posts.show"),
re_path( re_path(
r"^(?P<id>[-\w]+)/agenda.pdf$", views.show_pdf_agenda, name="show_pdf_agenda" r"^(?P<id>[-\w]+)/agenda.pdf$",
views.show_pdf_agenda,
name="show_pdf_agenda",
), ),
re_path( re_path(
r"^(?P<id>[-\w]+)/protokoll.pdf$", r"^(?P<id>[-\w]+)/protokoll.pdf$",
views.show_pdf_protocol, views.show_pdf_protocol,
name="show_pdf_protocol", name="show_pdf_protocol",
), ),
path("t/<str:tag>", views.tags, name="posts.tags"),
path("fet_calendar.ics", views.calendar, name="posts.calendar"),
path("func/tag_complete", tag_complete),
path("func/slug_calc", slug_calc),
] ]

View File

@@ -14,7 +14,7 @@ from documents.api import get_pad_link
from documents.etherpadlib import add_ep_cookie from documents.etherpadlib import add_ep_cookie
from members.models import Member, JobMember from members.models import Member, JobMember
from .forms import PostSearchForm from .forms import PostSearchForm
from .models import Post, FetMeeting, FileUpload from .models import Event, FetMeeting, FileUpload, Post
from .utils import render_to_pdf from .utils import render_to_pdf
@@ -28,6 +28,8 @@ def index(request):
compact_view = None compact_view = None
fet_meeting_only = None fet_meeting_only = None
public_only = not request.user.is_authenticated
if request.method == "POST": if request.method == "POST":
if "btn_input" in request.POST: if "btn_input" in request.POST:
form = PostSearchForm(request.POST) form = PostSearchForm(request.POST)
@@ -53,12 +55,15 @@ def index(request):
request, "Es kann nicht nur nach einem Monat gesucht werden." request, "Es kann nicht nur nach einem Monat gesucht werden."
) )
posts = deque( posts = Post.objects.date_filtered_list(
Post.objects.get_date_filtered_list(year, month, fet_meeting_only) public_only,
year,
month,
fet_meeting_only,
) )
else: else:
form = PostSearchForm() form = PostSearchForm()
posts = deque(Post.objects.get_date_sorted_list()) posts = Post.objects.date_sorted_list(public_only)
if posts: if posts:
taglist = map(lambda post: post.tags, posts) taglist = map(lambda post: post.tags, posts)
@@ -75,20 +80,26 @@ def index(request):
def calendar(request): def calendar(request):
"Kalender Ansicht ICS zur Verknüpfung mit Outlook" """
events = deque(Post.objects.get_all_posts_with_date()) ICS-calendar for outlook, google calender,...
"""
# publish all events independent of authenticated user
events = Event.all_events.published(False)
context = {
"events": events,
}
return render( return render(
request, request, "posts/fet_calendar.ics", context, content_type="text/calendar"
"posts/fet_calendar.ics",
{"events": events},
content_type="text/calendar",
) )
def tags(request, tag=""): def tags(request, tag=""):
posts = deque(Post.objects.get_visible_articles().filter(tags__name=tag)) public_only = not request.user.is_authenticated
featured_post = Post.objects.get_visible_articles().filter(slug=tag).first()
posts = Post.objects.published(public_only).filter(tags__name=tag)
featured_post = Post.objects.published(public_only).filter(slug=tag).first()
job_members = JobMember.active_member.get_all_by_slug(slug=tag) job_members = JobMember.active_member.get_all_by_slug(slug=tag)
@@ -110,14 +121,14 @@ def tags(request, tag=""):
return render(request, "posts/tag.html", context) return render(request, "posts/tag.html", context)
def __get_post_object(id=None): def __get_post_object(id=None, public=True):
post = None post = None
try: try:
if id.isdigit() or id is int: if id.isdigit() or id is int:
post = Post.objects.get(id=int(id)) post = Post.objects.published(public).get(id=int(id))
elif id != "" and id is not None: elif id != "" and id is not None:
post = Post.objects.get(slug=id) post = Post.objects.published(public).get(slug=id)
except Exception: except Exception:
logger.info("Wrong id '{}'".format(id)) logger.info("Wrong id '{}'".format(id))
raise Http404("wrong post id") raise Http404("wrong post id")
@@ -126,49 +137,51 @@ def __get_post_object(id=None):
def show(request, id=None): def show(request, id=None):
p = __get_post_object(id) public_only = not request.user.is_authenticated
post = __get_post_object(id, public_only)
files = deque(FileUpload.objects.filter(post=p)) # files
files = FileUpload.objects.filter(post=post)
post_author = Member.all_members.filter(username=p.author).first() # author
author_image = None
author = None author = None
author_image = None
post_author = Member.all_members.filter(username=post.author).first()
if post_author: if post_author:
author_image = post_author.image["avatar"].url
author = post_author author = post_author
author_image = post_author.image["avatar"].url
# etherpad links for agenda and protocol
ep_agenda_link = "#" ep_agenda_link = "#"
ep_protocol_link = "#" ep_protocol_link = "#"
# set filename for pdf, not a nice solution # set filename for pdf, not a nice solution
filename_agenda = None filename_agenda = None
filename_protocol = None filename_protocol = None
if p.has_agenda: if post.has_agenda:
ep_agenda_link = get_pad_link(p.agenda_key) ep_agenda_link = get_pad_link(post.agenda_key)
if ep_agenda_link != "#": if ep_agenda_link != "#":
filename_agenda = p.slug + "-agenda.pdf" filename_agenda = post.slug + "-agenda.pdf"
if p.has_protocol: if post.has_protocol:
ep_protocol_link = get_pad_link(p.protocol_key) ep_protocol_link = get_pad_link(post.protocol_key)
if ep_protocol_link != "#": if ep_protocol_link != "#":
filename_protocol = p.slug + "-protokoll.pdf" filename_protocol = post.slug + "-protokoll.pdf"
related_posts = p.tags.similar_objects()
related_posts = post.tags.similar_objects()
# list of non 'is_hidden' posts for related_posts # list of non 'is_hidden' posts for related_posts
for obj in related_posts: for obj in related_posts:
if obj.is_hidden: if not obj.published:
related_posts.remove(obj) related_posts.remove(obj)
context = { context = {
"post": p, "post": post,
"files": files, "files": files,
"author": author, "author": author,
"author_image": author_image, "author_image": author_image,
"next": __get_next_dict(p), "next": __next(post, public_only),
"related_posts": related_posts[0:6], "related_posts": related_posts[0:6],
"ep_agenda_link": ep_agenda_link, "ep_agenda_link": ep_agenda_link,
"ep_protocol_link": ep_protocol_link, "ep_protocol_link": ep_protocol_link,
@@ -215,34 +228,33 @@ def show_pdf(request, html, filename):
def show_pdf_agenda(request, id): def show_pdf_agenda(request, id):
p = __get_post_object(id) post = __get_post_object(id)
html = p.agenda_html html = post.agenda_html
return show_pdf(request, html, p.slug + "-agenda") return show_pdf(request, html, post.slug + "-agenda")
@authenticated_user @authenticated_user
def show_pdf_protocol(request, id): def show_pdf_protocol(request, id):
p = __get_post_object(id) post = __get_post_object(id)
html = p.protocol_html html = post.protocol_html
return show_pdf(request, html, p.slug + "-protokoll") return show_pdf(request, html, post.slug + "-protokoll")
def __get_next_dict(post=None): def __next(post=None, public=True):
""" """
Helper function for getting next post Helper function for getting next post
""" """
# TODO: Docstring
posts = None posts = None
d = post.slug d = post.slug
if post: if post:
# TODO: bad implementation but it works!! # TODO: bad implementation but it works!!
if post.post_type == "N" or post.post_type == "E": if post.post_type == "N" or post.post_type == "E":
posts = Post.articles.get_visible_articles() posts = Post.articles.date_sorted_list(public)
elif post.post_type == "F": elif post.post_type == "F":
posts = FetMeeting.objects.get_queryset().order_by("-event_start") posts = FetMeeting.objects.published(public)
if posts: if posts:
for k, v in enumerate(posts): for k, v in enumerate(posts):