Skip to content

Commit

Permalink
Merge pull request #654 from alan-turing-institute/rss_feed
Browse files Browse the repository at this point in the history
adds rss/atom feeds for public experiences
  • Loading branch information
gedankenstuecke authored Feb 12, 2024
2 parents 7382e4b + 658d700 commit 23352dd
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 4 deletions.
59 changes: 59 additions & 0 deletions server/apps/main/feeds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from .models import PublicExperience
from django.contrib.syndication.views import Feed
from django.urls import reverse
from server.apps.main.helpers import extract_triggers_to_show, expand_filter
from django.utils.feedgenerator import Atom1Feed

class PublicExperienceFeed(Feed):
description_template = "main/feed.html"

def get_object(self, request):
# check if 'all triggers' is in keys
all_triggers = request.GET.get("all_triggers", False)
# set all trigger labels if set
if all_triggers:
allowed_triggers = {
"abuse",
"violence",
"drug",
"mentalhealth",
"negbody",
"other",
}
else:
# Check the allowed triggers
allowed_triggers = set(request.GET.keys())
triggers_to_show = extract_triggers_to_show(allowed_triggers)
return triggers_to_show

def title(self, obj):
return "AutSPACEs public experiences"

def link(self, obj):
return reverse("main:public_experiences")

def description(self, obj):
joined_triggers = ", ".join(obj)
if joined_triggers:
return "This feed includes potentially triggering stories related to %s" % joined_triggers
else:
return "No triggering content is included in this feed"

def item_link(self, item):
return reverse('main:single_story', args=[item.experience_id])

def item_title(self, item):
return item.title_text

def item_pubdate(self, item):
return item.created_at

def items(self, obj):
experiences = PublicExperience.objects.filter(moderation_status="approved")
experiences = expand_filter(experiences, obj)
experiences = experiences.order_by("-created_at")[:10]
return experiences

class PublicExperienceAtomFeed(PublicExperienceFeed):
feed_type = Atom1Feed
subtitle = PublicExperienceFeed.description
6 changes: 6 additions & 0 deletions server/apps/main/templates/main/application.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
<link href="{% static '/css/main.css' %}" rel="stylesheet">
{%block page_css%} {% endblock %}

<!-- RSS links where appropriate -->
{% if rss_link %}
<link rel="alternate" type="application/rss+xml" href="{{rss_link}}">
<link rel="alternate" type="application/atom+xml" href="{{atom_link}}">
{% endif %}

</head>

<body {% block body_attributes%} {% endblock %}>
Expand Down
5 changes: 2 additions & 3 deletions server/apps/main/templates/main/experiences_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ <h1 class="big-heading">View Stories</h1>
</div>
</div>
</div>

</form>
</div>
{% if searched %}
Expand All @@ -144,8 +143,6 @@ <h1 class="big-heading">View Stories</h1>
</div>
{% endif %}
</section>


<section id="stories-post">
<div class="container-fluid story-text">
{% for experience in experiences %}
Expand Down Expand Up @@ -229,6 +226,8 @@ <h4 class="story-card-title">Recommendation</h4>
<!-- Add Pagination -->
{% include 'main/pagination.html' with stories=experiences page_query_param='page' %}
{% endif %}
<div class="form-text">
<a href="{{atom_link}}" <i class="bi bi-rss"></i> You can also subscribe to this page as a feed</a>. The current trigger options will be preserved.</div>
</div>
</section>

Expand Down
10 changes: 10 additions & 0 deletions server/apps/main/templates/main/feed.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

<h2>The experience</h2>
<p>
{{ obj.experience_text }}
</p>

<h2>What would make a difference</h2>
<p>
{{ obj.difference_text }}
</p>
23 changes: 23 additions & 0 deletions server/apps/main/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,3 +804,26 @@ def test_my_stories_pagination_page2(self):
assert len(stories) == min(num_items_per_page, n_stories)
# check story numbering
assert stories[0]['number'] == num_items_per_page + 1 # first story on page 1 is continuation of page 1



def test_feeds(self):
c = Client()
c.force_login(self.user_a)
response = c.get("/main/public_experiences/rss.xml")
assert response.status_code == 200
self.assertTemplateUsed(response, "main/feed.html")
# Check that there is only one story visible - the one with no triggering labels
self.assertContains(response,"No triggering content is included in this feed")
self.assertContains(response,"<item>", count=1)

# If you allow the abuse tag there should be 2 stories one with no tags one with the abuse tag
search_response_abuse = c.get("/main/public_experiences/rss.xml?abuse=True")
self.assertNotContains(search_response_abuse,"No triggering content is included in this feed")
self.assertContains(search_response_abuse,"<item>", count=2)


search_response_t = c.get("/main/public_experiences/rss.xml?all_triggers=True")
self.assertContains(search_response_t,"<item>", count=2)


3 changes: 3 additions & 0 deletions server/apps/main/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.urls import path, re_path
from server.apps.main import views
from server.apps.main import feeds

app_name = "main"

Expand Down Expand Up @@ -33,4 +34,6 @@
path("registration/", views.registration, name="registration"),
path("single_story/<uuid>/",views.single_story,name="single_story"),
path("success_confirm/", views.success_confirm, name="success_confirm"),
path("public_experiences/rss.xml", feeds.PublicExperienceFeed(), name='rss_feed'),
path("public_experiences/atom.xml", feeds.PublicExperienceAtomFeed(), name='atom_feed'),
]
5 changes: 4 additions & 1 deletion server/apps/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,10 @@ def list_public_experiences(request):

exp_context = {"experiences": page_experiences}

context = {**tts, **exp_context, **search_context}
rss_link = reverse("main:rss_feed") + "?" + request.GET.urlencode()
atom_link = rss_link = reverse("main:atom_feed") + "?" + request.GET.urlencode()

context = {'rss_link': rss_link, 'atom_link': atom_link, **tts, **exp_context, **search_context}

# Standard page showing all moderated stories
return render(request, "main/experiences_page.html", context=context)
Expand Down

0 comments on commit 23352dd

Please sign in to comment.