Update web app manifest; fix type errors
All checks were successful
Deploy to Server / deploy (push) Successful in 18s
|
|
@ -30,6 +30,9 @@ def get_urls_from_sitemap(sitemap_url: str, list_of_urls: list[str]) -> list[str
|
||||||
if parser.has_sitemaps():
|
if parser.has_sitemaps():
|
||||||
sitemaps: SitemapIndex = parser.get_sitemaps()
|
sitemaps: SitemapIndex = parser.get_sitemaps()
|
||||||
for sitemap in sitemaps:
|
for sitemap in sitemaps:
|
||||||
|
if not sitemap.loc:
|
||||||
|
continue
|
||||||
|
|
||||||
list_of_urls.extend(
|
list_of_urls.extend(
|
||||||
get_urls_from_sitemap(
|
get_urls_from_sitemap(
|
||||||
sitemap_url=sitemap.loc,
|
sitemap_url=sitemap.loc,
|
||||||
|
|
@ -39,7 +42,7 @@ def get_urls_from_sitemap(sitemap_url: str, list_of_urls: list[str]) -> list[str
|
||||||
|
|
||||||
elif parser.has_urls():
|
elif parser.has_urls():
|
||||||
urls: UrlSet = parser.get_urls()
|
urls: UrlSet = parser.get_urls()
|
||||||
list_of_urls.extend(url.loc for url in urls)
|
list_of_urls.extend(url.loc for url in urls if url.loc)
|
||||||
|
|
||||||
return list_of_urls
|
return list_of_urls
|
||||||
|
|
||||||
|
|
@ -99,6 +102,7 @@ class Command(BaseCommand):
|
||||||
api_key_location=api_key_location,
|
api_key_location=api_key_location,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
status_code: int = 0
|
||||||
urls: list[str] = get_urls_from_sitemap(sitemap_url=sitemap, list_of_urls=[])
|
urls: list[str] = get_urls_from_sitemap(sitemap_url=sitemap, list_of_urls=[])
|
||||||
chucked_urls: list[list[str]] = get_chucked_urls(urls=urls)
|
chucked_urls: list[list[str]] = get_chucked_urls(urls=urls)
|
||||||
for chunk in chucked_urls:
|
for chunk in chucked_urls:
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ def _build_seo_context( # noqa: PLR0913, PLR0917
|
||||||
|
|
||||||
|
|
||||||
def _render_urlset_xml(
|
def _render_urlset_xml(
|
||||||
url_entries: list[dict[str, str | dict[str, str]]],
|
url_entries: list[dict[str, str]],
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Render a <urlset> sitemap XML string from URL entries.
|
"""Render a <urlset> sitemap XML string from URL entries.
|
||||||
|
|
||||||
|
|
@ -184,20 +184,24 @@ def sitemap_view(request: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
# Compute last modified per-section so search engines can more intelligently crawl.
|
# Compute last modified per-section so search engines can more intelligently crawl.
|
||||||
# Do not fabricate a lastmod date if the section has no data.
|
# Do not fabricate a lastmod date if the section has no data.
|
||||||
twitch_channels_lastmod = Channel.objects.aggregate(max=Max("updated_at"))["max"]
|
twitch_channels_lastmod: datetime.datetime | None = Channel.objects.aggregate(
|
||||||
twitch_drops_lastmod = max(
|
max=Max("updated_at"),
|
||||||
[
|
)["max"]
|
||||||
|
|
||||||
|
twitch_drops_lastmod: datetime.datetime | None = max(
|
||||||
|
(
|
||||||
dt
|
dt
|
||||||
for dt in [
|
for dt in [
|
||||||
DropCampaign.objects.aggregate(max=Max("updated_at"))["max"],
|
DropCampaign.objects.aggregate(max=Max("updated_at"))["max"],
|
||||||
RewardCampaign.objects.aggregate(max=Max("updated_at"))["max"],
|
RewardCampaign.objects.aggregate(max=Max("updated_at"))["max"],
|
||||||
]
|
]
|
||||||
if dt is not None
|
if dt is not None
|
||||||
]
|
),
|
||||||
or [None],
|
default=None,
|
||||||
)
|
)
|
||||||
twitch_others_lastmod = max(
|
|
||||||
[
|
twitch_others_lastmod: datetime.datetime | None = max(
|
||||||
|
(
|
||||||
dt
|
dt
|
||||||
for dt in [
|
for dt in [
|
||||||
Game.objects.aggregate(max=Max("updated_at"))["max"],
|
Game.objects.aggregate(max=Max("updated_at"))["max"],
|
||||||
|
|
@ -205,10 +209,13 @@ def sitemap_view(request: HttpRequest) -> HttpResponse:
|
||||||
ChatBadgeSet.objects.aggregate(max=Max("updated_at"))["max"],
|
ChatBadgeSet.objects.aggregate(max=Max("updated_at"))["max"],
|
||||||
]
|
]
|
||||||
if dt is not None
|
if dt is not None
|
||||||
]
|
),
|
||||||
or [None],
|
default=None,
|
||||||
)
|
)
|
||||||
kick_lastmod = KickDropCampaign.objects.aggregate(max=Max("updated_at"))["max"]
|
|
||||||
|
kick_lastmod: datetime.datetime | None = KickDropCampaign.objects.aggregate(
|
||||||
|
max=Max("updated_at"),
|
||||||
|
)["max"]
|
||||||
|
|
||||||
sitemap_entries: list[dict[str, str]] = [
|
sitemap_entries: list[dict[str, str]] = [
|
||||||
{"loc": f"{base_url}/sitemap-static.xml"},
|
{"loc": f"{base_url}/sitemap-static.xml"},
|
||||||
|
|
@ -297,7 +304,7 @@ def sitemap_static_view(request: HttpRequest) -> HttpResponse:
|
||||||
"youtube:index",
|
"youtube:index",
|
||||||
]
|
]
|
||||||
|
|
||||||
sitemap_urls: list[dict[str, str | dict[str, str]]] = []
|
sitemap_urls: list[dict[str, str]] = []
|
||||||
for route_name in static_route_names:
|
for route_name in static_route_names:
|
||||||
url = reverse(route_name)
|
url = reverse(route_name)
|
||||||
sitemap_urls.append({"url": f"{base_url}{url}"})
|
sitemap_urls.append({"url": f"{base_url}{url}"})
|
||||||
|
|
@ -317,13 +324,13 @@ def sitemap_twitch_channels_view(request: HttpRequest) -> HttpResponse:
|
||||||
HttpResponse: The rendered sitemap XML.
|
HttpResponse: The rendered sitemap XML.
|
||||||
"""
|
"""
|
||||||
base_url: str = _build_base_url(request)
|
base_url: str = _build_base_url(request)
|
||||||
sitemap_urls: list[dict[str, str | dict[str, str]]] = []
|
sitemap_urls: list[dict[str, str]] = []
|
||||||
|
|
||||||
channels: QuerySet[Channel] = Channel.objects.all()
|
channels: QuerySet[Channel] = Channel.objects.all()
|
||||||
for channel in channels:
|
for channel in channels:
|
||||||
resource_url: str = reverse("twitch:channel_detail", args=[channel.twitch_id])
|
resource_url: str = reverse("twitch:channel_detail", args=[channel.twitch_id])
|
||||||
full_url: str = f"{base_url}{resource_url}"
|
full_url: str = f"{base_url}{resource_url}"
|
||||||
entry: dict[str, str | dict[str, str]] = {"url": full_url}
|
entry: dict[str, str] = {"url": full_url}
|
||||||
if channel.updated_at:
|
if channel.updated_at:
|
||||||
entry["lastmod"] = channel.updated_at.isoformat()
|
entry["lastmod"] = channel.updated_at.isoformat()
|
||||||
sitemap_urls.append(entry)
|
sitemap_urls.append(entry)
|
||||||
|
|
@ -343,16 +350,16 @@ def sitemap_twitch_drops_view(request: HttpRequest) -> HttpResponse:
|
||||||
HttpResponse: The rendered sitemap XML.
|
HttpResponse: The rendered sitemap XML.
|
||||||
"""
|
"""
|
||||||
base_url: str = _build_base_url(request)
|
base_url: str = _build_base_url(request)
|
||||||
sitemap_urls: list[dict[str, str | dict[str, str]]] = []
|
sitemap_urls: list[dict[str, str]] = []
|
||||||
|
|
||||||
campaigns: QuerySet[DropCampaign] = DropCampaign.objects.all()
|
campaigns: QuerySet[DropCampaign] = DropCampaign.objects.all()
|
||||||
for campaign in campaigns:
|
for campaign in campaigns:
|
||||||
resource_url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
resource_url: str = reverse("twitch:campaign_detail", args=[campaign.twitch_id])
|
||||||
full_url: str = f"{base_url}{resource_url}"
|
full_url: str = f"{base_url}{resource_url}"
|
||||||
entry: dict[str, str] = {"url": full_url}
|
campaign_url_entry: dict[str, str] = {"url": full_url}
|
||||||
if campaign.updated_at:
|
if campaign.updated_at:
|
||||||
entry["lastmod"] = campaign.updated_at.isoformat()
|
campaign_url_entry["lastmod"] = campaign.updated_at.isoformat()
|
||||||
sitemap_urls.append(entry)
|
sitemap_urls.append(campaign_url_entry)
|
||||||
|
|
||||||
reward_campaigns: QuerySet[RewardCampaign] = RewardCampaign.objects.all()
|
reward_campaigns: QuerySet[RewardCampaign] = RewardCampaign.objects.all()
|
||||||
for reward_campaign in reward_campaigns:
|
for reward_campaign in reward_campaigns:
|
||||||
|
|
@ -362,11 +369,13 @@ def sitemap_twitch_drops_view(request: HttpRequest) -> HttpResponse:
|
||||||
)
|
)
|
||||||
|
|
||||||
full_url: str = f"{base_url}{resource_url}"
|
full_url: str = f"{base_url}{resource_url}"
|
||||||
entry: dict[str, str | dict[str, str]] = {"url": full_url}
|
reward_campaign_url_entry: dict[str, str] = {"url": full_url}
|
||||||
if reward_campaign.updated_at:
|
if reward_campaign.updated_at:
|
||||||
entry["lastmod"] = reward_campaign.updated_at.isoformat()
|
reward_campaign_url_entry["lastmod"] = (
|
||||||
|
reward_campaign.updated_at.isoformat()
|
||||||
|
)
|
||||||
|
|
||||||
sitemap_urls.append(entry)
|
sitemap_urls.append(reward_campaign_url_entry)
|
||||||
|
|
||||||
xml_content: str = _render_urlset_xml(sitemap_urls)
|
xml_content: str = _render_urlset_xml(sitemap_urls)
|
||||||
return HttpResponse(xml_content, content_type="application/xml")
|
return HttpResponse(xml_content, content_type="application/xml")
|
||||||
|
|
@ -383,13 +392,13 @@ def sitemap_twitch_others_view(request: HttpRequest) -> HttpResponse:
|
||||||
HttpResponse: The rendered sitemap XML.
|
HttpResponse: The rendered sitemap XML.
|
||||||
"""
|
"""
|
||||||
base_url: str = _build_base_url(request)
|
base_url: str = _build_base_url(request)
|
||||||
sitemap_urls: list[dict[str, str | dict[str, str]]] = []
|
sitemap_urls: list[dict[str, str]] = []
|
||||||
|
|
||||||
games: QuerySet[Game] = Game.objects.all()
|
games: QuerySet[Game] = Game.objects.all()
|
||||||
for game in games:
|
for game in games:
|
||||||
resource_url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
resource_url: str = reverse("twitch:game_detail", args=[game.twitch_id])
|
||||||
full_url: str = f"{base_url}{resource_url}"
|
full_url: str = f"{base_url}{resource_url}"
|
||||||
entry: dict[str, str | dict[str, str]] = {"url": full_url}
|
entry: dict[str, str] = {"url": full_url}
|
||||||
|
|
||||||
if game.updated_at:
|
if game.updated_at:
|
||||||
entry["lastmod"] = game.updated_at.isoformat()
|
entry["lastmod"] = game.updated_at.isoformat()
|
||||||
|
|
@ -400,7 +409,7 @@ def sitemap_twitch_others_view(request: HttpRequest) -> HttpResponse:
|
||||||
for org in orgs:
|
for org in orgs:
|
||||||
resource_url: str = reverse("twitch:organization_detail", args=[org.twitch_id])
|
resource_url: str = reverse("twitch:organization_detail", args=[org.twitch_id])
|
||||||
full_url: str = f"{base_url}{resource_url}"
|
full_url: str = f"{base_url}{resource_url}"
|
||||||
entry: dict[str, str | dict[str, str]] = {"url": full_url}
|
entry: dict[str, str] = {"url": full_url}
|
||||||
|
|
||||||
if org.updated_at:
|
if org.updated_at:
|
||||||
entry["lastmod"] = org.updated_at.isoformat()
|
entry["lastmod"] = org.updated_at.isoformat()
|
||||||
|
|
@ -431,13 +440,13 @@ def sitemap_kick_view(request: HttpRequest) -> HttpResponse:
|
||||||
HttpResponse: The rendered sitemap XML.
|
HttpResponse: The rendered sitemap XML.
|
||||||
"""
|
"""
|
||||||
base_url: str = _build_base_url(request)
|
base_url: str = _build_base_url(request)
|
||||||
sitemap_urls: list[dict[str, str | dict[str, str]]] = []
|
sitemap_urls: list[dict[str, str]] = []
|
||||||
|
|
||||||
kick_campaigns: QuerySet[KickDropCampaign] = KickDropCampaign.objects.all()
|
kick_campaigns: QuerySet[KickDropCampaign] = KickDropCampaign.objects.all()
|
||||||
for campaign in kick_campaigns:
|
for campaign in kick_campaigns:
|
||||||
resource_url: str = reverse("kick:campaign_detail", args=[campaign.kick_id])
|
resource_url: str = reverse("kick:campaign_detail", args=[campaign.kick_id])
|
||||||
full_url: str = f"{base_url}{resource_url}"
|
full_url: str = f"{base_url}{resource_url}"
|
||||||
entry: dict[str, str | dict[str, str]] = {"url": full_url}
|
entry: dict[str, str] = {"url": full_url}
|
||||||
|
|
||||||
if campaign.updated_at:
|
if campaign.updated_at:
|
||||||
entry["lastmod"] = campaign.updated_at.isoformat()
|
entry["lastmod"] = campaign.updated_at.isoformat()
|
||||||
|
|
@ -466,7 +475,7 @@ def sitemap_youtube_view(request: HttpRequest) -> HttpResponse:
|
||||||
"""
|
"""
|
||||||
base_url: str = _build_base_url(request)
|
base_url: str = _build_base_url(request)
|
||||||
|
|
||||||
sitemap_urls: list[dict[str, str | dict[str, str]]] = [
|
sitemap_urls: list[dict[str, str]] = [
|
||||||
{"url": f"{base_url}{reverse('youtube:index')}"},
|
{"url": f"{base_url}{reverse('youtube:index')}"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -980,7 +989,7 @@ def dashboard(request: HttpRequest) -> HttpResponse:
|
||||||
kick_campaigns_by_game[game_key]["campaigns"].append({
|
kick_campaigns_by_game[game_key]["campaigns"].append({
|
||||||
"campaign": campaign,
|
"campaign": campaign,
|
||||||
"channels": list(campaign.channels.all()),
|
"channels": list(campaign.channels.all()),
|
||||||
"rewards": list(campaign.rewards.all()),
|
"rewards": list(campaign.rewards.all()), # pyright: ignore[reportAttributeAccessIssue]
|
||||||
})
|
})
|
||||||
|
|
||||||
active_reward_campaigns: QuerySet[RewardCampaign] = (
|
active_reward_campaigns: QuerySet[RewardCampaign] = (
|
||||||
|
|
|
||||||
|
|
@ -56,18 +56,29 @@ def _build_seo_context(
|
||||||
"robots_directive": "index, follow",
|
"robots_directive": "index, follow",
|
||||||
}
|
}
|
||||||
if seo_meta:
|
if seo_meta:
|
||||||
if seo_meta.get("page_url"):
|
page_url: str | None = seo_meta.get("page_url")
|
||||||
context["page_url"] = seo_meta["page_url"]
|
if page_url:
|
||||||
if seo_meta.get("og_type"):
|
context["page_url"] = page_url
|
||||||
context["og_type"] = seo_meta["og_type"]
|
|
||||||
if seo_meta.get("robots_directive"):
|
og_type: str | None = seo_meta.get("og_type")
|
||||||
context["robots_directive"] = seo_meta["robots_directive"]
|
if og_type:
|
||||||
if seo_meta.get("schema_data"):
|
context["og_type"] = og_type
|
||||||
context["schema_data"] = json.dumps(seo_meta["schema_data"])
|
|
||||||
if seo_meta.get("published_date"):
|
robots_directive: str | None = seo_meta.get("robots_directive")
|
||||||
context["published_date"] = seo_meta["published_date"]
|
if robots_directive:
|
||||||
if seo_meta.get("modified_date"):
|
context["robots_directive"] = robots_directive
|
||||||
context["modified_date"] = seo_meta["modified_date"]
|
|
||||||
|
schema_data: dict[str, Any] | None = seo_meta.get("schema_data")
|
||||||
|
if schema_data:
|
||||||
|
context["schema_data"] = json.dumps(schema_data)
|
||||||
|
|
||||||
|
published_date: str | None = seo_meta.get("published_date")
|
||||||
|
if published_date:
|
||||||
|
context["published_date"] = published_date
|
||||||
|
|
||||||
|
modified_date: str | None = seo_meta.get("modified_date")
|
||||||
|
if modified_date:
|
||||||
|
context["modified_date"] = modified_date
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
static/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
1
static/favicon.svg
Normal file
|
After Width: | Height: | Size: 31 KiB |
|
|
@ -1,19 +1,28 @@
|
||||||
{
|
{
|
||||||
"name": "ttvdrops",
|
"name": "ttvdrops.lovinator.space",
|
||||||
"short_name": "ttvdrops",
|
"short_name": "TTVDrops",
|
||||||
|
"description": "Track Twitch and Kick drops.",
|
||||||
|
"start_url": "/",
|
||||||
|
"scope": "/",
|
||||||
|
"display": "standalone",
|
||||||
|
"categories": [
|
||||||
|
"games",
|
||||||
|
"utilities"
|
||||||
|
],
|
||||||
|
"theme_color": "#0c227f",
|
||||||
|
"background_color": "#000000",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "web-app-manifest-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "web-app-manifest-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"theme_color": "#ffffff",
|
|
||||||
"background_color": "#ffffff",
|
|
||||||
"display": "standalone"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
static/web-app-manifest-192x192.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
static/web-app-manifest-512x512.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -5,6 +5,16 @@
|
||||||
<link rel="apple-touch-icon"
|
<link rel="apple-touch-icon"
|
||||||
sizes="180x180"
|
sizes="180x180"
|
||||||
href="{% static 'apple-touch-icon.png' %}" />
|
href="{% static 'apple-touch-icon.png' %}" />
|
||||||
|
<meta name="apple-mobile-web-app-title" content="TTVDrops" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="{% static 'favicon.ico' %}" />
|
||||||
|
<link rel="shortcut icon"
|
||||||
|
type="image/x-icon"
|
||||||
|
href="{% static 'favicon.ico' %}" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="{% static 'favicon.svg' %}" />
|
||||||
|
<link rel="icon"
|
||||||
|
type="image/png"
|
||||||
|
sizes="96x96"
|
||||||
|
href="{% static 'favicon-96x96.png' %}" />
|
||||||
<link rel="icon"
|
<link rel="icon"
|
||||||
type="image/png"
|
type="image/png"
|
||||||
sizes="32x32"
|
sizes="32x32"
|
||||||
|
|
|
||||||
|
|
@ -147,27 +147,46 @@ def _build_seo_context(
|
||||||
"robots_directive": "index, follow",
|
"robots_directive": "index, follow",
|
||||||
}
|
}
|
||||||
if seo_meta:
|
if seo_meta:
|
||||||
if seo_meta.get("page_url"):
|
page_url = seo_meta.get("page_url")
|
||||||
context["page_url"] = seo_meta["page_url"]
|
if page_url:
|
||||||
if seo_meta.get("og_type"):
|
context["page_url"] = page_url
|
||||||
context["og_type"] = seo_meta["og_type"]
|
|
||||||
if seo_meta.get("robots_directive"):
|
og_type = seo_meta.get("og_type")
|
||||||
context["robots_directive"] = seo_meta["robots_directive"]
|
if og_type:
|
||||||
if seo_meta.get("page_image"):
|
context["og_type"] = og_type
|
||||||
context["page_image"] = seo_meta["page_image"]
|
|
||||||
if seo_meta.get("page_image_width") and seo_meta.get("page_image_height"):
|
robots_directive = seo_meta.get("robots_directive")
|
||||||
context["page_image_width"] = seo_meta["page_image_width"]
|
if robots_directive:
|
||||||
context["page_image_height"] = seo_meta["page_image_height"]
|
context["robots_directive"] = robots_directive
|
||||||
if seo_meta.get("schema_data"):
|
|
||||||
context["schema_data"] = json.dumps(seo_meta["schema_data"])
|
page_image = seo_meta.get("page_image")
|
||||||
if seo_meta.get("breadcrumb_schema"):
|
if page_image:
|
||||||
context["breadcrumb_schema"] = json.dumps(seo_meta["breadcrumb_schema"])
|
context["page_image"] = page_image
|
||||||
if seo_meta.get("pagination_info"):
|
page_image_width = seo_meta.get("page_image_width")
|
||||||
context["pagination_info"] = seo_meta["pagination_info"]
|
page_image_height = seo_meta.get("page_image_height")
|
||||||
if seo_meta.get("published_date"):
|
if page_image_width and page_image_height:
|
||||||
context["published_date"] = seo_meta["published_date"]
|
context["page_image_width"] = page_image_width
|
||||||
if seo_meta.get("modified_date"):
|
context["page_image_height"] = page_image_height
|
||||||
context["modified_date"] = seo_meta["modified_date"]
|
|
||||||
|
schema_data = seo_meta.get("schema_data")
|
||||||
|
if schema_data:
|
||||||
|
context["schema_data"] = json.dumps(schema_data)
|
||||||
|
|
||||||
|
breadcrumb_schema = seo_meta.get("breadcrumb_schema")
|
||||||
|
if breadcrumb_schema:
|
||||||
|
context["breadcrumb_schema"] = json.dumps(breadcrumb_schema)
|
||||||
|
|
||||||
|
pagination_info = seo_meta.get("pagination_info")
|
||||||
|
if pagination_info:
|
||||||
|
context["pagination_info"] = pagination_info
|
||||||
|
|
||||||
|
published_date = seo_meta.get("published_date")
|
||||||
|
if published_date:
|
||||||
|
context["published_date"] = published_date
|
||||||
|
|
||||||
|
modified_date = seo_meta.get("modified_date")
|
||||||
|
if modified_date:
|
||||||
|
context["modified_date"] = modified_date
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||