~sirn/fanboi2

e28d50e3a4dbb8d02c3c1f70eaaa2b283abe7d33 — Kridsada Thanabulpong 4 years ago 9f07aeb
Allow topic and board to be expanded.
M fanboi2/serializers.py => fanboi2/serializers.py +8 -3
@@ 51,7 51,7 @@ def _board_serializer(obj, request):
        'title': obj.title,
        'path': request.route_path('api_board', board=obj.slug),
    }
    if request.params.get('topics'):
    if request.params.get('topics') and not 'board' in request.params:
        result['topics'] = obj.topics.limit(10)
    return result



@@ 78,7 78,9 @@ def _topic_serializer(obj, request):
        'title': obj.title,
        'path': request.route_path('api_topic', topic=obj.id),
    }
    if request.params.get('posts'):
    if request.params.get('board'):
        result['board'] = obj.board
    if request.params.get('posts') and not 'topic' in request.params:
        result['posts'] = obj.recent_posts()
    return result



@@ 93,7 95,7 @@ def _post_serializer(obj, request):
    :type request: pyramid.request.Request
    :rtype: dict
    """
    return {
    result = {
        'type': 'post',
        'id': obj.id,
        'body': obj.body,


@@ 110,6 112,9 @@ def _post_serializer(obj, request):
            query=obj.number,
        ),
    }
    if request.params.get('topic'):
        result['topic'] = obj.topic
    return result


def _page_serializer(obj, request):

M fanboi2/templates/api/_boards.mako => fanboi2/templates/api/_boards.mako +14 -0
@@ 116,6 116,20 @@
                            </td>
                        </tr>
                        <tr class="api-table-row">
                            <th class="api-table-item title">status</th>
                            <td class="api-table-item type">String</td>
                            <td class="api-table-item">
                                <p>Status string whether the board is still active or not. Available values are:</p>
                                <ul>
                                    <li><strong>open</strong> — the board is postable.</li>
                                    <li><strong>restricted</strong> — the board is postable but no new topics can be made.</li>
                                    <li><strong>locked</strong> — the board could not be posted.</li>
                                    <li><strong>archived</strong> — the board could not be posted and is no longer listed in board list.</li>
                                </ul>
                                <pre class="codeblock">"status":"open"</pre>
                            </td>
                        </tr>
                        <tr class="api-table-row">
                            <th class="api-table-item title">title</th>
                            <td class="api-table-item type">String</td>
                            <td class="api-table-item">

M fanboi2/templates/api/_posts.mako => fanboi2/templates/api/_posts.mako +36 -0
@@ 47,6 47,24 @@
            <div class="api-request-endpoint"><span class="api-request-verb verb-get">GET</span> ${formatters.unquoted_path(request, 'api_topic_posts', topic='{api-topic.id}')}</div>
            <div class="api-request-body">
                <p>Use this endpoint to retrieve a list of posts associated to the specific topic. By default this API will returns all posts. For a more specific query scope, please see <a href="#api-topic-posts-scoped">#api-topic-posts-scoped</a>.</p>
                <table class="api-table">
                    <thead class="api-table-header">
                        <tr class="api-table-row">
                            <th class="api-table-item title">Query string</th>
                            <th class="api-table-item title">Description</th>
                        </tr>
                    </thead>
                    <tbody class="api-table-body">
                        <tr class="api-table-row">
                            <th class="api-table-item title">?topic=1</th>
                            <td class="api-table-item">Include the topic in a <code>topic</code> object.</td>
                        </tr>
                        <tr class="api-table-row">
                            <th class="api-table-item title">?board=1</th>
                            <td class="api-table-item">Include the board in a <code>boards</code> object. Only if <code>topic</code> is present.</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>


@@ 191,6 209,24 @@
                        </tr>
                    </tbody>
                </table>
                <table class="api-table">
                    <thead class="api-table-header">
                        <tr class="api-table-row">
                            <th class="api-table-item title">Query string</th>
                            <th class="api-table-item title">Description</th>
                        </tr>
                    </thead>
                    <tbody class="api-table-body">
                        <tr class="api-table-row">
                            <th class="api-table-item title">?topic=1</th>
                            <td class="api-table-item">Include the topic in a <code>topic</code> object.</td>
                        </tr>
                        <tr class="api-table-row">
                            <th class="api-table-item title">?board=1</th>
                            <td class="api-table-item">Include the board in a <code>boards</code> object. Only if <code>topic</code> is present.</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>

M fanboi2/templates/api/_topics.mako => fanboi2/templates/api/_topics.mako +8 -0
@@ 56,6 56,10 @@
                    </thead>
                    <tbody class="api-table-body">
                        <tr class="api-table-row">
                            <th class="api-table-item title">?board=1</th>
                            <td class="api-table-item">Include the board in a <code>board</code> object.</td>
                        </tr>
                        <tr class="api-table-row">
                            <th class="api-table-item title">?posts=1</th>
                            <td class="api-table-item">Include the recent 30 posts in a <code>posts</code> object.</td>
                        </tr>


@@ 90,6 94,10 @@
                    </thead>
                    <tbody class="api-table-body">
                        <tr class="api-table-row">
                            <th class="api-table-item title">?board=1</th>
                            <td class="api-table-item">Include the board in a <code>board</code> object.</td>
                        </tr>
                        <tr class="api-table-row">
                            <th class="api-table-item title">?posts=1</th>
                            <td class="api-table-item">Include the recent 30 posts in a <code>posts</code> object.</td>
                        </tr>

M fanboi2/tests/test_serializers.py => fanboi2/tests/test_serializers.py +81 -0
@@ 82,12 82,24 @@ class TestJSONRendererWithModel(ModelMixin, RegistryMixin, unittest.TestCase):

    def test_board_with_topics(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')
        request = self._makeRequest(params={'topics': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_board', '/board/{board}/')
        config.add_route('api_topic', '/board/{topic}/')
        response = self._makeOne(board, request=request)
        self.assertIn('topics', response)

    def test_board_with_topics_board(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')
        request = self._makeRequest(params={'topics': True, 'board': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_board', '/board/{board}/')
        config.add_route('api_topic', '/board/{topic}/')
        response = self._makeOne(board, request=request)
        self.assertNotIn('topics', response)

    def test_topic(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')


@@ 106,6 118,28 @@ class TestJSONRendererWithModel(ModelMixin, RegistryMixin, unittest.TestCase):
        self.assertIn('status', response)
        self.assertNotIn('posts', response)

    def test_topic_with_board(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')
        request = self._makeRequest(params={'board': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_topic', '/topic/{topic}/')
        config.add_route('api_board', '/board/{board}/')
        response = self._makeOne(topic, request=request)
        self.assertEqual(response['board_id'], board.id)
        self.assertIn('board', response)

    def test_topic_with_board_topics(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')
        request = self._makeRequest(params={'board': True, 'topics': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_topic', '/topic/{topic}/')
        config.add_route('api_board', '/board/{board}/')
        response = self._makeOne(topic, request=request)
        self.assertIn('board', response)
        self.assertNotIn('topics', response['board'])

    def test_topic_with_posts(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')


@@ 117,6 151,17 @@ class TestJSONRendererWithModel(ModelMixin, RegistryMixin, unittest.TestCase):
        self.assertEqual(response['board_id'], board.id)
        self.assertIn('posts', response)

    def test_topic_with_posts_topic(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Heavenly Moon')
        request = self._makeRequest(params={'posts': True, 'topic': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_topic', '/topic/{topic}/')
        response = self._makeOne(topic, request=request)
        self.assertEqual(response['title'], 'Heavenly Moon')
        self.assertEqual(response['board_id'], board.id)
        self.assertNotIn('posts', response)

    def test_post(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Baz')


@@ 139,6 184,42 @@ class TestJSONRendererWithModel(ModelMixin, RegistryMixin, unittest.TestCase):
        self.assertIn('number', response)
        self.assertNotIn('ip_address', response)

    def test_post_with_topic(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Baz')
        post = self._makePost(topic=topic, body='Hello, world!')
        request = self._makeRequest(params={'topic': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_topic', '/topic/{topic}/')
        config.add_route('api_topic_posts_scoped', '/topic/{topic}/{query}/')
        response = self._makeOne(post, request=request)
        self.assertIn('topic', response)

    def test_post_with_topic_board(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Baz')
        post = self._makePost(topic=topic, body='Hello, world!')
        request = self._makeRequest(params={'topic': True, 'board': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_board', '/board/{board}/')
        config.add_route('api_topic', '/topic/{topic}/')
        config.add_route('api_topic_posts_scoped', '/topic/{topic}/{query}/')
        response = self._makeOne(post, request=request)
        self.assertIn('topic', response)
        self.assertIn('board', response['topic'])

    def test_post_with_topic_posts(self):
        board = self._makeBoard(title='Foobar', slug='foo')
        topic = self._makeTopic(board=board, title='Baz')
        post = self._makePost(topic=topic, body='Hello, world!')
        request = self._makeRequest(params={'topic': True, 'posts': True})
        config = self._makeConfig(request, self._makeRegistry())
        config.add_route('api_topic', '/topic/{topic}/')
        config.add_route('api_topic_posts_scoped', '/topic/{topic}/{query}/')
        response = self._makeOne(post, request=request)
        self.assertIn('topic', response)
        self.assertNotIn('posts', response['topic'])

    def test_page(self):
        page = self._makePage(title='Test', body='**Test**', slug='test')
        request = self._makeRequest()