~homeworkprod/byceps

4ca65ed7daa2a57a3130f1d23facc751b241acda — Jochen Kupperschmidt 9 months ago 0f32dde
Move rendering of news item body to service
2 files changed, 27 insertions(+), 25 deletions(-)

M byceps/blueprints/site/news/views.py
M byceps/services/news/service.py
M byceps/blueprints/site/news/views.py => byceps/blueprints/site/news/views.py +0 -21
@@ 6,11 6,8 @@ byceps.blueprints.site.news.views
:License: Revised BSD (see `LICENSE` file for details)
"""

import dataclasses

from flask import abort, g

from ....services.news import html_service as news_html_service
from ....services.news import service as news_item_service
from ....services.site import (
    service as site_service,


@@ 45,11 42,6 @@ def index(page):
        channel_id, page, items_per_page, published_only=published_only
    )

    replacement_items = [
        _replace_body_with_rendered_body(item) for item in items.items
    ]
    items.items = replacement_items

    return {
        'items': items,
        'page': page,


@@ 70,8 62,6 @@ def view(slug):
    if item is None:
        abort(404)

    item = _replace_body_with_rendered_body(item)

    return {
        'item': item,
    }


@@ 100,14 90,3 @@ def _get_items_per_page_value():

def _may_view_drafts(user):
    return user.has_permission(NewsItemPermission.view_draft)


def _replace_body_with_rendered_body(item):
    try:
        rendered_body = news_html_service.render_body(
            item.body, item.channel.id, item.images
        )
    except Exception as e:
        rendered_body = None  # Not the best error indicator.

    return dataclasses.replace(item, body=rendered_body)

M byceps/services/news/service.py => byceps/services/news/service.py +27 -4
@@ 6,7 6,9 @@ byceps.services.news.service
:License: Revised BSD (see `LICENSE` file for details)
"""

import dataclasses
from datetime import datetime
from functools import partial
from typing import Dict, Optional, Sequence

from ...database import db, paginate, Pagination, Query


@@ 16,6 18,7 @@ from ...typing import UserID
from ..user import service as user_service

from .channel_service import _db_entity_to_channel
from . import html_service
from .models.channel import Channel as DbChannel
from .models.item import (
    CurrentVersionAssociation as DbCurrentVersionAssociation,


@@ 187,7 190,7 @@ def find_aggregated_item_by_slug(
    if item is None:
        return None

    return _db_entity_to_item(item)
    return _db_entity_to_item(item, render_body=True)


def get_aggregated_items_paginated(


@@ 203,7 206,9 @@ def get_aggregated_items_paginated(
    if published_only:
        query = query.published()

    return paginate(query, page, items_per_page, item_mapper=_db_entity_to_item)
    item_mapper = partial(_db_entity_to_item, render_body=True)

    return paginate(query, page, items_per_page, item_mapper=item_mapper)


def get_items_paginated(


@@ 259,7 264,9 @@ def get_item_count_by_channel_id() -> Dict[ChannelID, int]:
    return dict(channel_ids_and_item_counts)


def _db_entity_to_item(item: DbItem) -> Item:
def _db_entity_to_item(
    item: DbItem, *, render_body: Optional[bool] = False
) -> Item:
    channel = _db_entity_to_channel(item.channel)
    external_url = item.channel.url_prefix + item.slug
    image_url_path = _assemble_image_url_path(item)


@@ 268,7 275,7 @@ def _db_entity_to_item(item: DbItem) -> Item:
        for image in item.images
    ]

    return Item(
    item = Item(
        id=item.id,
        channel=channel,
        slug=item.slug,


@@ 281,6 288,11 @@ def _db_entity_to_item(item: DbItem) -> Item:
        images=images,
    )

    if render_body:
        item = _replace_body_with_rendered_body(item)

    return item


def _assemble_image_url_path(item: DbItem) -> Optional[str]:
    url_path = item.current_version.image_url_path


@@ 289,3 301,14 @@ def _assemble_image_url_path(item: DbItem) -> Optional[str]:
        return None

    return f'/data/global/news_channels/{item.channel_id}/{url_path}'


def _replace_body_with_rendered_body(item: Item) -> Item:
    try:
        rendered_body = html_service.render_body(
            item.body, item.channel.id, item.images
        )
    except Exception as e:
        rendered_body = None  # Not the best error indicator.

    return dataclasses.replace(item, body=rendered_body)