Skip to content

Commit d379b4c

Browse files
ihalaij1markkuriekkinen
authored andcommitted
Improve sitemaps with dynamic priorities
* Old courses have a smaller priority than current courses. * Add a new base class for sitemaps: `class AplusSitemap`. It differentiates the priorities of recent and outdated objects. * Change some of the priority values that had been used. Give chapters the highest priority. * Remove anchor URLs from the sitemap because sitemaps disallow the anchor part (for example, embedded exercises with `#chapter-exercise-1`). * No duplicate URLs in the sitemap. * For embedded exercises under chapters, add the `noindex` meta tag on the full-view exercise page so that it is not indexed. Only the chapter page should be indexed since students use the chapter view. Fixes apluslms#975
1 parent bfc3637 commit d379b4c

File tree

6 files changed

+79
-24
lines changed

6 files changed

+79
-24
lines changed

aplus/settings.py

+6
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,12 @@
158158
'aplus_auth',
159159
)
160160

161+
# Sitemap settings
162+
##########################################################################
163+
164+
# A course is considered recent or upcoming if it was/is open within this delta (in days) from now.
165+
SITEMAP_DELTA_DAYS_RECENT_OR_UPCOMING = 180
166+
161167
# Different login options (may override in local_settings.py)
162168
##########################################################################
163169

course/sitemaps.py

+7-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.urls.base import reverse
33
from django.utils import timezone
44

5+
from lib.sitemaps import AplusSitemap
56
from .models import CourseInstance, CourseModule
67

78

@@ -19,32 +20,28 @@ def location(self, item):
1920
return reverse(item)
2021

2122

22-
class InstanceSitemap(sitemaps.Sitemap):
23-
priority = 1.0
23+
class InstanceSitemap(AplusSitemap):
2424
changefreq = 'daily'
25+
base_priority = 0.4
2526

2627
def items(self):
2728
return CourseInstance.objects.filter(
2829
view_content_to=CourseInstance.VIEW_ACCESS.PUBLIC,
30+
visible_to_students=True,
2931
)
3032

31-
def location(self, item):
32-
return item.get_display_url()
33-
3433

35-
class ModuleSitemap(sitemaps.Sitemap):
36-
priority = 0.2
34+
class ModuleSitemap(AplusSitemap):
3735
changefreq = 'daily'
36+
base_priority = 0.2
3837

3938
def items(self):
4039
return CourseModule.objects.filter(
4140
course_instance__view_content_to=CourseInstance.VIEW_ACCESS.PUBLIC,
41+
course_instance__visible_to_students=True,
4242
opening_time__lte=timezone.now(),
4343
)
4444

45-
def location(self, item):
46-
return item.get_display_url()
47-
4845

4946
all_sitemaps = {
5047
'course_static': CourseStaticViewSitemap,

exercise/sitemaps.py

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,47 @@
1-
from django.contrib import sitemaps
21
from django.urls.base import reverse
32
from django.utils import timezone
43

54
from course.models import CourseInstance
5+
from lib.sitemaps import AplusSitemap
66
from .models import BaseExercise, CourseChapter, LearningObject
77

88

9-
class BaseExerciseSitemap(sitemaps.Sitemap):
10-
priority = 0.2
9+
class BaseExerciseSitemap(AplusSitemap):
1110
changefreq = 'daily'
11+
base_priority = 0.5
1212

1313
def items(self):
1414
return BaseExercise.objects.filter(
1515
course_module__course_instance__view_content_to=CourseInstance.VIEW_ACCESS.PUBLIC,
16+
course_module__course_instance__visible_to_students=True,
1617
course_module__opening_time__lte=timezone.now(),
17-
status__in=[LearningObject.STATUS.READY, LearningObject.STATUS.UNLISTED],
18+
status=LearningObject.STATUS.READY,
1819
audience=LearningObject.AUDIENCE.COURSE_AUDIENCE,
20+
parent__isnull=True,
1921
)
2022

21-
def location(self, item):
22-
return item.get_display_url()
23-
2423

25-
class CourseChapterSitemap(sitemaps.Sitemap):
26-
priority = 1.0
24+
class CourseChapterSitemap(AplusSitemap):
2725
changefreq = 'daily'
2826

2927
def items(self):
3028
return CourseChapter.objects.filter(
3129
course_module__course_instance__view_content_to=CourseInstance.VIEW_ACCESS.PUBLIC,
30+
course_module__course_instance__visible_to_students=True,
3231
course_module__opening_time__lte=timezone.now(),
3332
status__in=[LearningObject.STATUS.READY, LearningObject.STATUS.UNLISTED],
3433
audience=LearningObject.AUDIENCE.COURSE_AUDIENCE,
3534
)
3635

37-
def location(self, item):
38-
return item.get_display_url()
39-
4036

41-
class TableOfContentsSitemap(sitemaps.Sitemap):
42-
priority = 0.2
37+
class TableOfContentsSitemap(AplusSitemap):
4338
changefreq = 'monthly'
39+
base_priority = 0.2
4440

4541
def items(self):
4642
return CourseInstance.objects.filter(
4743
view_content_to=CourseInstance.VIEW_ACCESS.PUBLIC,
44+
visible_to_students=True,
4845
)
4946

5047
def location(self, item):

exercise/templates/exercise/exercise_base.html

+6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
{% endblock %}
3131
{% endblock %}
3232

33+
{% block meta %}
34+
{% if exercise.parent and exercise.status == exercise.STATUS.UNLISTED %}
35+
<meta name="robots" content="noindex">
36+
{% endif %}
37+
{% endblock %}
38+
3339
{% block columns %}
3440
<div class="{% if exercise.use_wide_column %}col-lg-12{% else %}col-lg-9{% endif %} exercise-column">
3541

lib/sitemaps.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import datetime
2+
3+
from django.conf import settings
4+
from django.contrib import sitemaps
5+
from django.utils import timezone
6+
7+
from course.models import CourseInstance, CourseModule
8+
from exercise.models import BaseExercise, CourseChapter
9+
10+
11+
class AplusSitemap(sitemaps.Sitemap):
12+
# The base priority for pages from old courses.
13+
# Pages of recent or upcoming courses have the base priority multiplied.
14+
base_priority = 0.5
15+
16+
def is_recent_or_upcoming(self, item):
17+
"""
18+
Return a boolean value indicating if the given item is open now
19+
or if either the item's start date or end date is within a certain time delta from now.
20+
"""
21+
if isinstance(item, CourseInstance):
22+
start_date = item.starting_time
23+
end_date = item.ending_time
24+
elif isinstance(item, CourseModule):
25+
start_date = item.opening_time
26+
end_date = item.closing_time
27+
elif isinstance(item, (BaseExercise, CourseChapter)):
28+
start_date = item.course_module.opening_time
29+
end_date = item.course_module.closing_time
30+
else:
31+
return False
32+
now = timezone.now()
33+
delta = datetime.timedelta(settings.SITEMAP_DELTA_DAYS_RECENT_OR_UPCOMING)
34+
is_recent_or_upcoming = (
35+
item.is_open(now)
36+
or now - delta <= start_date <= now + delta
37+
or now - delta <= end_date <= now + delta
38+
)
39+
return is_recent_or_upcoming
40+
41+
def location(self, item):
42+
return item.get_display_url()
43+
44+
def priority(self, item):
45+
return min(1.0, 2 * self.base_priority) if self.is_recent_or_upcoming(item) else self.base_priority

templates/base.html

+4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
{# Put all additional scripts inside this block. #}
6767
{% endblock %}
6868

69+
{% block meta %}
70+
{# Put all additional meta data inside this block. #}
71+
{% endblock %}
72+
6973
<!-- Some favicons courtesy of http://realfavicongenerator.net/ -->
7074
<link rel="apple-touch-icon" sizes="57x57" href="{{ STATIC_URL }}favicons/apple-touch-icon-57x57.png">
7175
<link rel="apple-touch-icon" sizes="114x114" href="{{ STATIC_URL }}favicons/apple-touch-icon-114x114.png">

0 commit comments

Comments
 (0)