Merge pull request #3 from mediacms-io/feat-search-rss

introduce rss and custom rss
This commit is contained in:
Markos Gogoulos 2020-12-25 15:48:06 +02:00 committed by GitHub
commit fed0234034
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 173 additions and 14 deletions

View File

@ -37,4 +37,5 @@ def stuff(request):
ret[ ret[
"VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE" "VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE"
] = settings.VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE ] = settings.VIDEO_PLAYER_FEATURED_VIDEO_ON_INDEX_PAGE
ret["RSS_URL"] = "/rss"
return ret return ret

View File

@ -1,20 +1,72 @@
from django.contrib.syndication.views import Feed from django.contrib.syndication.views import Feed
from django.utils.feedgenerator import Rss201rev2Feed
from django.urls import reverse from django.urls import reverse
from django.db.models import Q from django.db.models import Q
from django.conf import settings
from django.contrib.postgres.search import SearchQuery
from .models import Media from .models import Media, Category
from . import helpers
from .stop_words import STOP_WORDS
class RssMediaFeed(Feed): class MediaRSSFeed(Rss201rev2Feed):
def rss_attributes(self):
attrs = super(MediaRSSFeed, self).rss_attributes()
attrs["xmlns:media"] = "http://search.yahoo.com/mrss/"
attrs["xmlns:atom"] = "http://www.w3.org/2005/Atom"
return attrs
def add_item_elements(self, handler, item):
"""Callback to add elements to each item (item/entry) element."""
super(MediaRSSFeed, self).add_item_elements(handler, item)
if "media:title" in item:
handler.addQuickElement("media:title", item["title"])
if "media:description" in item:
handler.addQuickElement("media:description", item["description"])
if "content_url" in item:
content = dict(url=item["content_url"])
if "content_width" in item:
content["width"] = str(item["content_width"])
if "content_height" in item:
content["height"] = str(item["content_height"])
handler.addQuickElement("media:content", "", content)
if "thumbnail_url" in item:
thumbnail = dict(url=item["thumbnail_url"])
if "thumbnail_width" in item:
thumbnail["width"] = str(item["thumbnail_width"])
if "thumbnail_height" in item:
thumbnail["height"] = str(item["thumbnail_height"])
handler.addQuickElement("media:thumbnail", "", thumbnail)
if "keywords" in item:
handler.addQuickElement("media:keywords", item["keywords"])
def add_root_elements(self, handler):
super().add_root_elements(handler)
if self.feed["author_name"] is not None:
handler.startElement("author", {})
handler.addQuickElement("name", self.feed["author_name"])
handler.endElement("author")
if self.feed.get("published") is not None:
handler.startElement("published", {})
handler.addQuickElement("name", self.feed["published"])
handler.endElement("published")
class IndexRSSFeed(Feed):
feed_type = MediaRSSFeed
title = "Latest Media" title = "Latest Media"
link = "/media" link = "/rss"
description = "Latest Media RSS feed" description = "Latest Media RSS feed"
def items(self): def items(self):
basic_query = Q(listable=True) media = Media.objects.filter(listable=True).order_by("-add_date")
media = Media.objects.filter(basic_query).order_by("-add_date")
media = media.prefetch_related("user") media = media.prefetch_related("user")
return media[:40] return media[:20]
def item_title(self, item): def item_title(self, item):
return item.title return item.title
@ -22,5 +74,97 @@ class RssMediaFeed(Feed):
def item_description(self, item): def item_description(self, item):
return item.description return item.description
def item_author_name(self, item):
return item.user.username
def item_pubdate(self, item):
return item.add_date
def item_updateddate(self, item):
return item.edit_date
def item_link(self, item): def item_link(self, item):
return reverse("get_media") + "?m={0}".format(item.friendly_token) return reverse("get_media") + "?m={0}".format(item.friendly_token)
def item_extra_kwargs(self, item):
item = {
"media:title": item.title,
"media:description": item.description,
"content_width": 720,
"thumbnail_url": f"{settings.SSL_FRONTEND_HOST}/{item.poster_url}",
"content_url": f"{settings.SSL_FRONTEND_HOST}/{item.get_absolute_url()}",
"thumbnail_width": 720,
}
return item
class SearchRSSFeed(Feed):
feed_type = MediaRSSFeed
description = "Latest Media RSS feed"
def link(self, obj):
return f"/rss/search"
def get_object(self, request):
category = request.GET.get("c", "")
tag = request.GET.get("t", "")
query = request.GET.get("q", "")
media = Media.objects.filter(listable=True)
if category:
media = media.filter(category__title=category)
elif tag:
media = media.filter(tags__title=tag)
elif query:
# same as on files.views.MediaSearch: move this processing to a prepare_query function
query = helpers.clean_query(query)
q_parts = [
q_part.rstrip("y")
for q_part in query.split()
if q_part not in STOP_WORDS
]
if q_parts:
query = SearchQuery(q_parts[0] + ":*", search_type="raw")
for part in q_parts[1:]:
query &= SearchQuery(part + ":*", search_type="raw")
else:
query = None
if query:
media = media.filter(search=query)
media = media.order_by("-add_date").prefetch_related("user")
return media
def items(self, objects):
return objects[:20]
def item_title(self, item):
return item.title
def item_description(self, item):
return item.description
def item_author_name(self, item):
return item.user.username
def item_pubdate(self, item):
return item.add_date
def item_updateddate(self, item):
return item.edit_date
def item_link(self, item):
return reverse("get_media") + "?m={0}".format(item.friendly_token)
def item_extra_kwargs(self, item):
item = {
"media:title": item.title,
"media:description": item.description,
"content_width": 720,
"thumbnail_url": f"{settings.SSL_FRONTEND_HOST}/{item.poster_url}",
"content_url": f"{settings.SSL_FRONTEND_HOST}/{item.get_absolute_url()}",
"thumbnail_width": 720,
}
return item

View File

@ -137,11 +137,10 @@ class CommentList(APIView):
serializer = CommentSerializer(page, many=True, context={"request": request}) serializer = CommentSerializer(page, many=True, context={"request": request})
return paginator.get_paginated_response(serializer.data) return paginator.get_paginated_response(serializer.data)
def delete(self, request, format=None): def delete(self, request, format=None):
comment_ids = request.GET.get('comment_ids') comment_ids = request.GET.get("comment_ids")
if comment_ids: if comment_ids:
comments = comment_ids.split(',') comments = comment_ids.split(",")
Comment.objects.filter(uid__in=comments).delete() Comment.objects.filter(uid__in=comments).delete()
return Response(status=status.HTTP_204_NO_CONTENT) return Response(status=status.HTTP_204_NO_CONTENT)
@ -161,6 +160,7 @@ class UserList(APIView):
params = self.request.query_params params = self.request.query_params
ordering = params.get("ordering", "").strip() ordering = params.get("ordering", "").strip()
sort_by = params.get("sort_by", "").strip() sort_by = params.get("sort_by", "").strip()
role = params.get("role", "all").strip()
sort_by_options = ["date_added", "name"] sort_by_options = ["date_added", "name"]
if sort_by not in sort_by_options: if sort_by not in sort_by_options:
@ -173,11 +173,16 @@ class UserList(APIView):
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
qs = User.objects.filter() qs = User.objects.filter()
media = qs.order_by(f"{ordering}{sort_by}") if role == "manager":
qs = qs.filter(is_manager=True)
elif role == "editor":
qs = qs.filter(is_editor=True)
users = qs.order_by(f"{ordering}{sort_by}")
paginator = pagination_class() paginator = pagination_class()
page = paginator.paginate_queryset(media, request) page = paginator.paginate_queryset(users, request)
serializer = UserSerializer(page, many=True, context={"request": request}) serializer = UserSerializer(page, many=True, context={"request": request})
return paginator.get_paginated_response(serializer.data) return paginator.get_paginated_response(serializer.data)

View File

@ -5,7 +5,7 @@ from django.urls import path
from . import views from . import views
from . import management_views from . import management_views
from .feeds import RssMediaFeed from .feeds import IndexRSSFeed, SearchRSSFeed
urlpatterns = [ urlpatterns = [
url(r"^$", views.index), url(r"^$", views.index),
@ -33,7 +33,8 @@ urlpatterns = [
), ),
url(r"^popular$", views.recommended_media), url(r"^popular$", views.recommended_media),
url(r"^recommended$", views.recommended_media), url(r"^recommended$", views.recommended_media),
path("rss/", RssMediaFeed()), path("rss/", IndexRSSFeed()),
url("^rss/search", SearchRSSFeed()),
url(r"^search", views.search, name="search"), url(r"^search", views.search, name="search"),
url(r"^scpublisher", views.upload_media, name="upload_media"), url(r"^scpublisher", views.upload_media, name="upload_media"),
url(r"^tags", views.tags, name="tags"), url(r"^tags", views.tags, name="tags"),

View File

@ -296,6 +296,8 @@ def search(request):
"""Search view""" """Search view"""
context = {} context = {}
RSS_URL = f"/rss{request.environ['REQUEST_URI']}"
context["RSS_URL"] = RSS_URL
return render(request, "cms/search.html", context) return render(request, "cms/search.html", context)
@ -730,8 +732,13 @@ class MediaSearch(APIView):
media = Media.objects.filter(state="public", is_reviewed=True) media = Media.objects.filter(state="public", is_reviewed=True)
if query: if query:
# move this processing to a prepare_query function
query = clean_query(query) query = clean_query(query)
q_parts = [q_part for q_part in query.split() if q_part not in STOP_WORDS] q_parts = [
q_part.rstrip("y")
for q_part in query.split()
if q_part not in STOP_WORDS
]
if q_parts: if q_parts:
query = SearchQuery(q_parts[0] + ":*", search_type="raw") query = SearchQuery(q_parts[0] + ":*", search_type="raw")
for part in q_parts[1:]: for part in q_parts[1:]:

View File

@ -5,6 +5,7 @@
<link rel="manifest" href="{% static "favicons/site.webmanifest" %}"> <link rel="manifest" href="{% static "favicons/site.webmanifest" %}">
<link rel="mask-icon" href="{% static "favicons/safari-pinned-tab.svg" %}" color="#009933"> <link rel="mask-icon" href="{% static "favicons/safari-pinned-tab.svg" %}" color="#009933">
<link rel="shortcut icon" href="{% static "favicons/favicon.ico" %}"> <link rel="shortcut icon" href="{% static "favicons/favicon.ico" %}">
<link rel="alternate" type="application/rss+xml" title="RSS feeds" href="{{RSS_URL}}" />
<meta name="msapplication-TileColor" content="#ffffff"> <meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-config" content="{% static "favicons/browserconfig.xml" %}"> <meta name="msapplication-config" content="{% static "favicons/browserconfig.xml" %}">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">