Skip to content
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

INTR-305 - Move the events models/code into the content app - Step 1 #756

Draft
wants to merge 14 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
43 changes: 43 additions & 0 deletions src/content/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from .base_content import (
BasePage,
BasePageQuerySet,
ContentOwnerMixin,
ContentPage,
ContentPageQuerySet,
Theme,
)
from .blog import BlogIndex, BlogPost
# from .events import EventPage, EventsHome
from .navigation import NavigationPage
from .search import (
SearchExclusionPageLookUp,
SearchFieldsMixin,
SearchKeywordOrPhrase,
SearchKeywordOrPhraseQuerySet,
SearchPinPageLookUp,
)


__all__ = [
# base_content
"BasePage",
"BasePageQuerySet",
"ContentOwnerMixin",
"ContentPage",
"ContentPageQuerySet",
"Theme",
# blog
"BlogIndex",
"BlogPost",
# events
# "EventPage",
# "EventsHome",
# navigation
"NavigationPage",
# search
"SearchExclusionPageLookUp",
"SearchFieldsMixin",
"SearchKeywordOrPhrase",
"SearchKeywordOrPhraseQuerySet",
"SearchPinPageLookUp",
]
195 changes: 7 additions & 188 deletions src/content/models.py → src/content/models/base_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from typing import Optional

from django.contrib.auth import get_user_model
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models import Q, Subquery
from django.forms import widgets
Expand All @@ -24,10 +22,9 @@
from wagtail.snippets.models import register_snippet
from wagtail.utils.decorators import cached_classmethod

import dw_design_system.dwds.components as dwds_blocks
from content import blocks as content_blocks

from content.utils import (
get_search_content_for_block,
manage_excluded,
manage_pinned,
truncate_words_and_chars,
Expand All @@ -36,9 +33,14 @@
from extended_search.index import DWIndexedField as IndexedField
from extended_search.index import Indexed, RelatedFields
from peoplefinder.widgets import PersonChooser
from search.utils import split_query
from user.models import User as UserModel

from .search import (
SearchExclusionPageLookUp,
SearchFieldsMixin,
SearchPinPageLookUp,
)


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -258,77 +260,6 @@ def get_all_subclasses(cls):
return subclasses


class SearchFieldsMixin(models.Model):
"""
Specific fields and settings to manage search. Extra fields are generally
defined to make custom and specific indexing as defined in /docs/search.md

Usage:
- Add this mixin to a model
- Define the fields that should be indexed in search_stream_fields.
Example: ["body"]
- Add SearchFieldsMixin.indexed_fields to the Model's indexed_fields list
- Run self._generate_search_field_content() in full_clean() to generate
search fields
"""

class Meta:
abstract = True

search_stream_fields: list[str] = []

search_title = models.CharField(
max_length=255,
)
search_headings = models.TextField(
blank=True,
null=True,
)
search_content = models.TextField(
blank=True,
null=True,
)

def _generate_search_field_content(self):
self.search_title = self.title
search_headings = []
search_content = []

for stream_field_name in self.search_stream_fields:
stream_field = getattr(self, stream_field_name)
for stream_child in stream_field:
block_search_headings, block_search_content = (
get_search_content_for_block(stream_child.block, stream_child.value)
)
search_headings += block_search_headings
search_content += block_search_content

self.search_headings = " ".join(search_headings)
self.search_content = " ".join(search_content)

indexed_fields = [
IndexedField(
"search_title",
tokenized=True,
explicit=True,
fuzzy=True,
boost=5.0,
),
IndexedField(
"search_headings",
tokenized=True,
explicit=True,
fuzzy=True,
boost=3.0,
),
IndexedField(
"search_content",
tokenized=True,
explicit=True,
),
]


class ContentPage(SearchFieldsMixin, BasePage):
objects = PageManager.from_queryset(ContentPageQuerySet)()

Expand Down Expand Up @@ -518,115 +449,3 @@ def save(self, *args, **kwargs):
manage_pinned(self, self.pinned_phrases)

return super().save(*args, **kwargs)


class SearchKeywordOrPhrase(models.Model):
keyword_or_phrase = models.CharField(max_length=1000)
# TODO: Remove historical records.
history = HistoricalRecords()


class SearchKeywordOrPhraseQuerySet(models.QuerySet):
def filter_by_query(self, query):
query_parts = split_query(query)

return self.filter(search_keyword_or_phrase__keyword_or_phrase__in=query_parts)


class NavigationPage(SearchFieldsMixin, BasePage):
template = "content/navigation_page.html"

search_stream_fields: list[str] = ["primary_elements", "secondary_elements"]

primary_elements = StreamField(
[
("dw_navigation_card", dwds_blocks.NavigationCardBlock()),
],
blank=True,
)

secondary_elements = StreamField(
[
("dw_curated_page_links", dwds_blocks.CustomPageLinkListBlock()),
("dw_tagged_page_list", dwds_blocks.TaggedPageListBlock()),
("dw_cta", dwds_blocks.CTACardBlock()),
("dw_engagement_card", dwds_blocks.EngagementCardBlock()),
("dw_navigation_card", dwds_blocks.NavigationCardBlock()),
],
blank=True,
)

content_panels = BasePage.content_panels + [
FieldPanel("primary_elements"),
FieldPanel("secondary_elements"),
]

indexed_fields = SearchFieldsMixin.indexed_fields + [
IndexedField("primary_elements"),
IndexedField("secondary_elements"),
]

def get_template(self, request, *args, **kwargs):
return self.template

def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)

return context

def full_clean(self, *args, **kwargs):
self._generate_search_field_content()
super().full_clean(*args, **kwargs)


class SearchExclusionPageLookUp(models.Model):
objects = SearchKeywordOrPhraseQuerySet.as_manager()

search_keyword_or_phrase = models.ForeignKey(
SearchKeywordOrPhrase,
on_delete=models.CASCADE,
)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
# TODO: Remove historical records.
history = HistoricalRecords()


class SearchPinPageLookUp(models.Model):
objects = SearchKeywordOrPhraseQuerySet.as_manager()

search_keyword_or_phrase = models.ForeignKey(
SearchKeywordOrPhrase,
on_delete=models.CASCADE,
)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
# TODO: Remove historical records.
history = HistoricalRecords()


class BlogIndex(BasePage):
template = "content/blog_index.html"
subpage_types = [
"content.BlogPost",
]
is_creatable = False

def get_template(self, request, *args, **kwargs):
return self.template

def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
context["children"] = self.get_children().live().public().order_by("title")
return context


class BlogPost(ContentPage):
template = "content/blog_post.html"
subpage_types = []
is_creatable = True

def get_template(self, request, *args, **kwargs):
return self.template
31 changes: 31 additions & 0 deletions src/content/models/blog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import logging

from .base_content import BasePage, ContentPage


logger = logging.getLogger(__name__)


class BlogIndex(BasePage):
template = "content/blog_index.html"
subpage_types = [
"content.BlogPost",
]
is_creatable = False

def get_template(self, request, *args, **kwargs):
return self.template

def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
context["children"] = self.get_children().live().public().order_by("title")
return context


class BlogPost(ContentPage):
template = "content/blog_post.html"
subpage_types = []
is_creatable = True

def get_template(self, request, *args, **kwargs):
return self.template
Loading