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):
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())
def get_tags(lst):
@@ -17,28 +17,28 @@ def index(request):
t = set(t for t in get_tags(posts_for_tags))
# set the pinned post
featured_post = Post.articles.get_pinned_article()
if not featured_post:
pinned_post = Post.articles.pinned()
if not pinned_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
pinned_post = posts.popleft()
else:
# 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 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 = {
"posts": deque(list(posts)[:5]),
"events": Event.all_events.get_five_events(),
"featured_post": featured_post,
"events": Event.all_events.future_events()[:5],
"featured_post": pinned_post,
"featured_event": featured_event,
"featured_meeting": featured_meeting,
"tags_list": " ".join(t),

View File

@@ -55,9 +55,9 @@ class FileUploadInline(admin.TabularInline):
class PostAdmin(admin.ModelAdmin):
form = PostForm
model = Post
list_filter = ["is_pinned", "is_hidden"]
list_display = ["title", "slug", "public_date", "is_pinned", "is_hidden"]
ordering = ["is_hidden", "-public_date"]
list_filter = ["is_pinned", "status"]
list_display = ["title", "slug", "public_date", "status", "is_pinned"]
ordering = ["-public_date"]
def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {}
@@ -104,8 +104,8 @@ class NewsAdmin(PostAdmin):
class EventAdmin(PostAdmin):
form = EventForm
model = Event
list_filter = ["is_pinned"]
list_display = ["title", "slug", "event_start", "public_date", "is_pinned"]
list_filter = ["is_pinned", "status"]
list_display = ["title", "slug", "event_start", "status", "is_pinned"]
ordering = ["-event_start"]
actions = [make_fetmeeting]
@@ -114,7 +114,7 @@ class FetMeetingAdmin(EventAdmin):
form = FetMeetingForm
model = FetMeeting
list_filter = []
list_display = ["title", "slug", "event_start", "public_date"]
list_display = ["title", "slug", "event_start"]
actions = []

View File

@@ -39,13 +39,13 @@ class NewsForm(PostForm):
"title",
"subtitle",
"tags",
"status",
"image",
"body",
"slug",
"author",
"public_date",
"is_pinned",
"is_hidden",
]
labels = {
@@ -57,7 +57,6 @@ class NewsForm(PostForm):
"author": _("Autor"),
"public_date": _("Veröffentlichung"),
"is_pinned": _("Post anheften"),
"is_hidden": _("Post verstecken"),
}
help_texts = {
@@ -68,9 +67,6 @@ class NewsForm(PostForm):
"is_pinned": _(
"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")}
@@ -89,6 +85,7 @@ class EventForm(PostForm):
"title",
"subtitle",
"tags",
"status",
"image",
"body",
"event_start",

View File

@@ -1,20 +1,26 @@
from django.db import models
from django.db.models import Q
from django.db.models import Q, Manager
from django.utils import timezone
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):
return super().get_queryset().order_by("-public_date")
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
def get_date_sorted_list(self):
def date_sorted_list(self, public=True):
post_list = []
for post in self.get_visible_articles():
for post in self.published(public):
if post.post_type != "N":
post_list.append((post, post.event_start.date()))
else:
@@ -25,13 +31,20 @@ class PostManager(models.Manager):
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 = []
qs = self.published(public)
if not fet_meeting_only:
posts = self.get_visible_articles().filter(~Q(post_type="N"))
posts = qs.filter(~Q(post_type="N"))
else:
posts = self.get_visible_articles().filter(post_type="F")
posts = qs.filter(post_type="F")
if year:
posts = posts.filter(event_start__year=year)
@@ -42,7 +55,7 @@ class PostManager(models.Manager):
post_list.append((post, post.event_start.date()))
if not fet_meeting_only:
posts = self.get_visible_articles().filter(post_type="N")
posts = qs.filter(post_type="N")
if year:
posts = posts.filter(public_date__year=year)
@@ -57,40 +70,27 @@ class PostManager(models.Manager):
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()
return self.get_visible_articles().filter(
return self.published(public).filter(
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(models.Manager):
class ArticleManager(PublishedManager, 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")
)
qs = super().get_queryset().filter(Q(post_type="E") | Q(post_type="N"))
return qs.order_by("-public_date")
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
def get_date_sorted_list(self):
def date_sorted_list(self, public=True):
post_list = []
for post in self.get_visible_articles():
for post in self.published(public):
if post.post_type != "N":
post_list.append((post, post.event_start.date()))
else:
@@ -101,11 +101,11 @@ class ArticleManager(models.Manager):
return posts
def get_pinned_article(self):
return self.get_visible_articles().filter(is_pinned=True).first()
def pinned(self, public=True):
return self.published(public).filter(is_pinned=True).first()
class NewsManager(models.Manager):
class NewsManager(PublishedManager, Manager):
"""
Provide a query set only for "News"
"""
@@ -113,79 +113,60 @@ class NewsManager(models.Manager):
def get_queryset(self):
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(models.Manager):
class AllEventManager(PublishedManager, 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):
date_today = timezone.now()
return (
self.get_queryset()
.filter(event_start__gt=date_today)
.order_by("event_start")[:5]
super()
.get_queryset()
.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"
regular fet meetings should not be contained in the news stream
"""
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()
return (
self.get_queryset()
.filter(event_start__gt=date_today)
.order_by("event_start")
)
qs = self.published(public).filter(event_start__gt=date_today)
return qs.reverse()
def get_past_events(self):
def past_events(self, public=True):
date_today = timezone.now()
return (
self.get_queryset()
.filter(event_start__lt=date_today)
.order_by("-event_start")
)
qs = self.published(public).filter(event_start__lt=date_today)
return qs
class FetMeetingManager(models.Manager):
class FetMeetingManager(PublishedManager, Manager):
"""
Provide a query set only for "Fet Meeting"
"""
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()
return (
self.get_queryset()
.filter(event_start__gt=date_today)
.order_by("event_start")
)
qs = self.published().filter(event_start__gt=date_today)
return qs.reverse()
def _get_past_events(self):
def 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
qs = self.published().filter(event_start__lt=date_today)
return qs

View File

@@ -88,12 +88,21 @@ class Post(models.Model):
__choices = [("N", _("News")), ("E", _("Event")), ("F", _("FetMeeting"))]
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
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
event_start = models.DateTimeField(
verbose_name="Event Start", null=True, blank=True
@@ -263,6 +272,13 @@ class Post(models.Model):
)
super().clean()
@property
def published(self):
if self.status == self.Status.PUBLIC:
return True
return False
class News(Post):
objects = NewsManager()
@@ -342,6 +358,9 @@ class FetMeeting(Event):
if not self.event_end:
self.event_end = self.event_start + timedelta(hours=2)
# set FET Meeting always public
self.status = self.Status.PUBLIC
super().save(*args, **kwargs)
def __get_slug(self):

View File

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

View File

@@ -7,18 +7,20 @@ from .utils import slug_calc, tag_complete
app_name = apps.PostsConfig.name
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("fet_calendar.ics", views.calendar, name="posts.calendar"),
path("<str:id>", views.show, name="posts.show"),
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(
r"^(?P<id>[-\w]+)/protokoll.pdf$",
views.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 members.models import Member, JobMember
from .forms import PostSearchForm
from .models import Post, FetMeeting, FileUpload
from .models import Event, FetMeeting, FileUpload, Post
from .utils import render_to_pdf
@@ -28,6 +28,8 @@ def index(request):
compact_view = None
fet_meeting_only = None
public_only = not request.user.is_authenticated
if request.method == "POST":
if "btn_input" in request.POST:
form = PostSearchForm(request.POST)
@@ -53,12 +55,15 @@ def index(request):
request, "Es kann nicht nur nach einem Monat gesucht werden."
)
posts = deque(
Post.objects.get_date_filtered_list(year, month, fet_meeting_only)
posts = Post.objects.date_filtered_list(
public_only,
year,
month,
fet_meeting_only,
)
else:
form = PostSearchForm()
posts = deque(Post.objects.get_date_sorted_list())
posts = Post.objects.date_sorted_list(public_only)
if posts:
taglist = map(lambda post: post.tags, posts)
@@ -75,20 +80,26 @@ def index(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(
request,
"posts/fet_calendar.ics",
{"events": events},
content_type="text/calendar",
request, "posts/fet_calendar.ics", context, content_type="text/calendar"
)
def tags(request, tag=""):
posts = deque(Post.objects.get_visible_articles().filter(tags__name=tag))
featured_post = Post.objects.get_visible_articles().filter(slug=tag).first()
public_only = not request.user.is_authenticated
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)
@@ -110,14 +121,14 @@ def tags(request, tag=""):
return render(request, "posts/tag.html", context)
def __get_post_object(id=None):
def __get_post_object(id=None, public=True):
post = None
try:
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:
post = Post.objects.get(slug=id)
post = Post.objects.published(public).get(slug=id)
except Exception:
logger.info("Wrong id '{}'".format(id))
raise Http404("wrong post id")
@@ -126,49 +137,51 @@ def __get_post_object(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_image = None
# author
author = None
author_image = None
post_author = Member.all_members.filter(username=post.author).first()
if post_author:
author_image = post_author.image["avatar"].url
author = post_author
author_image = post_author.image["avatar"].url
# etherpad links for agenda and protocol
ep_agenda_link = "#"
ep_protocol_link = "#"
# set filename for pdf, not a nice solution
filename_agenda = None
filename_protocol = None
if p.has_agenda:
ep_agenda_link = get_pad_link(p.agenda_key)
if post.has_agenda:
ep_agenda_link = get_pad_link(post.agenda_key)
if ep_agenda_link != "#":
filename_agenda = p.slug + "-agenda.pdf"
filename_agenda = post.slug + "-agenda.pdf"
if p.has_protocol:
ep_protocol_link = get_pad_link(p.protocol_key)
if post.has_protocol:
ep_protocol_link = get_pad_link(post.protocol_key)
if ep_protocol_link != "#":
filename_protocol = p.slug + "-protokoll.pdf"
related_posts = p.tags.similar_objects()
filename_protocol = post.slug + "-protokoll.pdf"
related_posts = post.tags.similar_objects()
# list of non 'is_hidden' posts for related_posts
for obj in related_posts:
if obj.is_hidden:
if not obj.published:
related_posts.remove(obj)
context = {
"post": p,
"post": post,
"files": files,
"author": author,
"author_image": author_image,
"next": __get_next_dict(p),
"next": __next(post, public_only),
"related_posts": related_posts[0:6],
"ep_agenda_link": ep_agenda_link,
"ep_protocol_link": ep_protocol_link,
@@ -215,34 +228,33 @@ def show_pdf(request, html, filename):
def show_pdf_agenda(request, id):
p = __get_post_object(id)
html = p.agenda_html
post = __get_post_object(id)
html = post.agenda_html
return show_pdf(request, html, p.slug + "-agenda")
return show_pdf(request, html, post.slug + "-agenda")
@authenticated_user
def show_pdf_protocol(request, id):
p = __get_post_object(id)
html = p.protocol_html
post = __get_post_object(id)
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
"""
# TODO: Docstring
posts = None
d = post.slug
if post:
# TODO: bad implementation but it works!!
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":
posts = FetMeeting.objects.get_queryset().order_by("-event_start")
posts = FetMeeting.objects.published(public)
if posts:
for k, v in enumerate(posts):