如何在 Prolog 中将 CSS(带查询结果)添加到动态 reply_html_page 中?

How to add CSS (w/ query results) into dynamic reply_html_page in Prolog?

我真的很难过渡到 Prolog 中的编码。当用户从网页提交数据时,我会尝试 return 一个新页面,显示基于用户提交内容的查询结果。这是我到目前为止所拥有的。

编辑:(为完整源代码截取的替换代码)

:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/http_error)).
:- use_module(library(http/html_write)).
:- use_module(library(http/http_client)).
:- use_module(library(http/http_parameters)).
:- use_module(library(http/html_head)).
:- use_module(library(http/http_server_files)).

:- use_module(parts, [part/4]).

:- http_handler(root(.), main_query, []).
:- http_handler(root(search), search, []).
:- http_handler(root(search), part_results, []).

http:location(css, root(css), []).

server(Port) :-
    http_server(http_dispatch, [port(Port)]).

:- multifile
    user:body//2.

user:body(part_style, Body) -->
    html(body([
        div([id(top)], ['Parts']),
        div(id(content), Body)
        ])).

main_query(Request) :-
    reply_html_page(
        part_style,
        title('Beta Query'),
        [\page_content(Request)]).

page_content(_Request) -->
    {  http_link_to_id(search, [], Ref) },
    html([ \html_requires(css('part-style.css')),
        form([id(search), action='/search', method='POST'], [
        div([id(search_table)], [
            div([class(search_cell)], [
                label([for=part], ' '),
                select([name=part], \parts)
            ]),
            div([class(search_cell)], [
                label([for=major], ' '),
                select([name=major], \majors)
            ]),
            div([class(search_cell)], [
                label([for=minor], ' '),
                select([name=minor], \minors)
            ]),
            p([], [
                input([name=submit, class="button", type=submit,
                    value='Search'], [])
            ])
        ])
        ])
    ]).

css(URL) -->
    html_post(css,
        link([ type('text/css'),
        rel('stylesheet'),
        href(URL)
        ])).

part_results(Request) :-
    reply_html_page(part_style,
        [title('Part Results'),
        \css('part-style.css'),
        \html_receive(css)]).
%       \query_part).
% having trouble truing query_part into DCG.
query_part(Request) :-
    member(method(post), Request), !,
    http_read_data(Request, Data, []),
    format('Content-type: text/html~n~n', []),
    format('<p>', []),                                        
    memberchk(part=Part, Data),
    memberchk(major=M, Data),
    memberchk(minor=I, Data),
    atom_number(M, Major),
    atom_number(I, Minor),
    findall(p(Part, Major, Minor, Desc),
        part(Part, Major, Minor, Desc), Descriptions),
    maplist(desc, Descriptions),  
    format('</p>'),
    format('<a href="http://localhost:8000" class="button">Back</a>').

desc(p(P,M,I,D)) :- format("~q ~q:~q - ~q</br>", [P,M,I,D]).

parts -->
    { findall(P, part(P, Major, Minor, Desc), Parts),
        sort(Parts, Sorted) },
        options(Sorted).

majors -->
    { findall(M, part(Part, M, Minor, Desc), Majors),
        sort(Majors, Sorted) },
        options(Sorted).

minors -->
    { findall(I, part(Part, Major, I, Desc), Minors),
        sort(Minors, Sorted) },
        options(Sorted).

options([]) --> [].
options([O|Os]) -->
    html(option([value=O], O)),
    options(Os).

试图将此 query_part/1 定义为 DCG 让我很头疼。最初处理程序直接调用 part_query/1,但现在有一个调用 DCG 的 part_results 规则,并且 query_part 我们传递了一个请求参数。我一直在尝试阅读 DCG,但仍然不太了解它们,除了它们应该使编写规则更容易之外,我也不了解如何将 {} 与它们一起使用,我认为我需要这样做。 (但是,DCG 本身超出了这个问题的范围,因为它涵盖了很多,我可以继续尝试在其他地方理解它)。所以我仍在尝试将带有查询结果的 CSS 放入回复页面。

目前,CSS 出现在 HTML 的正文中。

非常感谢任何帮助。

我对此有几点评论:

立即解决

首先,为您的任务提供一个解决方案:要post资源,只需使用css//1 part_results/1 中的非终结符:

part_results(Request) :-
    reply_html_page(part_style,
                    [title('Part Results'),
                     \css('myfile.css'),
                     \html_receive(css)],
                    \query_part).

这足以得到你想要的。您使用 css//1 的方式与您在 HTTP 框架中使用任何其他非终端的方式完全相同,使用 (\)/1 espace 语法。

不同的解决方案

获得几乎相同结果的不同解决方案是使用html_requires//1:

part_results(Request) :-
    reply_html_page(part_style,
                    [title('Part Results'),
                     \html_requires(css('my-style.css'))],
                    \query_part).

这是来自 library(http/html_head) 的一个库谓词,基本上可以完成您当前正在做的事情手动

请注意,您需要使用 library(http/http_server_files) 来定义资源文件所需的位置。对于 CSS 文件,预定义位置是 root(css),因此您需要将 css 文件放在 css/* 中,这与您手动执行的操作不同。

为什么只有 body?

在您的原始示例中,为什么只发出了 body?答:因为你没有发出任何其他东西

请注意,除了使用 reply_html_page/3,您还可以简单地 自己在当前输出 上输出整个页面。这当然需要你发出你想要的一切,而不仅仅是body。

一般建议

下次,请 post 一个 self-contained 示例 ,不仅是部分片段,以便其他人更容易尝试您的代码。

这意味着:

  • 包括所有必要的库
  • 说明如何启动服务器
  • 显示如何访问服务器
  • 等等