Skip to content

Support of including blog in the website search #2136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions blog/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@

@admin.register(Entry)
class EntryAdmin(admin.ModelAdmin):
list_display = ("headline", "pub_date", "is_active", "is_published", "author")
list_filter = ("is_active",)
list_display = (
"headline",
"pub_date",
"is_active",
"is_published",
"is_searchable",
"author",
)
list_filter = ("is_active", "is_searchable")
exclude = ("summary_html", "body_html")
prepopulated_fields = {"slug": ("headline",)}
raw_id_fields = ["social_media_card"]
Expand Down
18 changes: 18 additions & 0 deletions blog/migrations/0006_entry_is_searchable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2 on 2025-07-24 07:21

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('blog', '0005_entry_social_media_card'),
]

operations = [
migrations.AddField(
model_name='entry',
name='is_searchable',
field=models.BooleanField(help_text='Tick to make this entry allow this entry to appear in the Django documentation search.', null=True),
),
]
19 changes: 19 additions & 0 deletions blog/migrations/0007_set_is_searchable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.2 on 2025-07-24 07:22

from django.db import migrations


def set_is_searchable(apps, schema_editor):
Entry = apps.get_model("blog", "Entry")
# If this is large, this should be split into batched updates
Entry.objects.filter(is_searchable__isnull=True).update(is_searchable=False)

class Migration(migrations.Migration):

dependencies = [
('blog', '0006_entry_is_searchable'),
]

operations = [
migrations.RunPython(set_is_searchable, reverse_code=migrations.RunPython.noop, elidable=True),
]
18 changes: 18 additions & 0 deletions blog/migrations/0008_alter_entry_is_searchable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2 on 2025-07-24 07:22

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('blog', '0007_set_is_searchable'),
]

operations = [
migrations.AlterField(
model_name='entry',
name='is_searchable',
field=models.BooleanField(default=False, help_text='Tick to make this entry allow this entry to appear in the Django documentation search.'),
),
]
2 changes: 1 addition & 1 deletion blog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def get_absolute_url(self):
"day": self.pub_date.strftime("%d").lower(),
"slug": self.slug,
}
return reverse("weblog:entry", kwargs=kwargs)
return reverse("weblog:entry", kwargs=kwargs, host="www")

def is_published(self):
"""
Expand Down
18 changes: 18 additions & 0 deletions docs/migrations/0007_documentrelease_support_end.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2 on 2025-07-23 16:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('docs', '0006_alter_document_metadata_noop'),
]

operations = [
migrations.AddField(
model_name='documentrelease',
name='support_end',
field=models.DateField(blank=True, help_text='The end of support for this release of Django.', null=True),
),
]
45 changes: 45 additions & 0 deletions docs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from django.utils.html import strip_tags
from django_hosts.resolvers import reverse

from blog.models import Entry
from releases.models import Release

from . import utils
Expand Down Expand Up @@ -95,6 +96,11 @@ class DocumentRelease(models.Model):
on_delete=models.CASCADE,
)
is_default = models.BooleanField(default=False)
support_end = models.DateField(
null=True,
blank=True,
help_text="The end of support for this release of Django.",
)

objects = DocumentReleaseQuerySet.as_manager()

Expand Down Expand Up @@ -212,6 +218,32 @@ def sync_to_db(self, decoded_documents):
)
document.save(update_fields=("metadata",))

def _sync_blog_to_db(self):
"""
Sync the blog entries into search based on the release documents
support end date.
"""
if self.lang == "en" and self.support_end:
for entry in Entry.objects.published(self.support_end):
Document.objects.create(
release=self,
path=entry.get_absolute_url(),
title=entry.headline,
metadata={
"body": entry.body_html,
"breadcrumbs": [
{"path": "weblog", "title": "News"},
],
"parents": "weblog",
"slug": entry.slug,
"title": entry.headline,
"toc": "",
},
config=TSEARCH_CONFIG_LANGUAGES.get(
self.lang[:2], DEFAULT_TEXT_SEARCH_CONFIG
),
)


def _clean_document_path(path):
# We have to be a bit careful to reverse-engineer the correct
Expand Down Expand Up @@ -382,3 +414,16 @@ def body(self):
with open(str(self.full_path)) as fp:
doc = json.load(fp)
return doc["body"]

def document_url(self):
if self.metadata["parents"] == "weblog":
return self.path
return reverse(
"document-detail",
kwargs={
"lang": self.release.lang,
"version": self.release.version,
"url": self.path,
},
host="docs",
)
1 change: 1 addition & 0 deletions docs/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class DocumentationCategory(TextChoices):
TOPICS = "topics", _("Using Django")
HOWTO = "howto", _("How-to guides")
RELEASE_NOTES = "releases", _("Release notes")
WEBSITE = "weblog", _("Django Website")

@classmethod
def parse(cls, value, default=None):
Expand Down
6 changes: 3 additions & 3 deletions docs/templates/docs/search_results.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ <h2>{% translate "No search query given" %}</h2>
{% for result in page.object_list %}
<dt>
<h2 class="result-title">
<a href="{% url 'document-detail' lang=result.release.lang version=result.release.version url=result.path host 'docs' %}{% if not start_sel in result.headline %}{{ result.highlight|fragment }}{% endif %}">{{ result.headline|safe }}</a>
<a href="{{ result.document_url }}{% if not start_sel in result.headline %}{{ result.highlight|fragment }}{% endif %}">{{ result.headline|safe }}</a>
</h2>
<span class="meta breadcrumbs">
{% for breadcrumb in result.breadcrumbs %}
<a href="{% url 'document-detail' lang=result.release.lang version=result.release.version url=breadcrumb.path host 'docs' %}">{{ breadcrumb.title }}</a>{% if not forloop.last %} <span class="arrow">»</span>{% endif %}
<a href="{{ result.document_url }}">{{ breadcrumb.title }}</a>{% if not forloop.last %} <span class="arrow">»</span>{% endif %}
{% endfor %}
</span>
</dt>
Expand All @@ -60,7 +60,7 @@ <h2 class="result-title">
<ul class="code-links">
{% for name, value in result_code_links.items %}
<li>
<a href="{% url 'document-detail' lang=result.release.lang version=result.release.version url=result.path host 'docs' %}#{{ value.full_path }}">
<a href="{{ result.document_url }}#{{ value.full_path }}">
<div>
<code>{{ name }}</code>
{% if value.module_path %}<div class="meta">{{ value.module_path }}</div>{% endif %}
Expand Down
Loading