mirror of
https://github.com/mediacms-io/mediacms.git
synced 2024-12-25 08:18:48 +01:00
Merge pull request #3 from mediacms-io/feat-search-rss
introduce rss and custom rss
This commit is contained in:
commit
fed0234034
@ -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
|
||||||
|
156
files/feeds.py
156
files/feeds.py
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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"),
|
||||||
|
@ -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:]:
|
||||||
|
@ -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">
|
||||||
|
Loading…
Reference in New Issue
Block a user