Clojure/compojure:如何处理来自Web表单的用户输入?

Clojure/compojure:如何处理来自Web表单的用户输入?,clojure,routes,compojure,numeric-input,Clojure,Routes,Compojure,Numeric Input,我正在制作一个Clojure web应用程序来处理数字输入数据。我已经设置了主页,正在通过按钮处理和显示提交后的输入数据 带注释的关键代码位: (defn process-grades "Takes user input from home's form-to function and processes it into the final grades list" [weights grades] (->> grades (map

我正在制作一个Clojure web应用程序来处理数字输入数据。我已经设置了主页,正在通过按钮处理和显示提交后的输入数据

带注释的关键代码位:

(defn process-grades 
      "Takes user input from home's form-to function and processes it into the final grades list"
      [weights grades]
    (->> grades
         (map (partial percentify-vector weights))  ;; <- The functions being called here are omitted but defined in the same name space.
         (mapv #(apply + %))))


    (defn home [& [weights grades error]]
  (html
    [:head
    [:title "Home | Clojuregrade"]]
    [:body
    [:h1 "Welcome to Clojuregrade"]
    [:p error]
    [:hr]
   (form-to [:post "/"]
    [:h3 "Enter the weights for each of the grades below. Of course, all of the numbers should add up to 100%. Be sure to include the brackets"
    [:br]
     (text-area {:cols 30 :placeholder "[40 10 50] <- adds up to 100%"} "weights" weights)]
    [:h3 "Enter ALL of the grades for EACH STUDENT in your class.
      Make sure that each of the grades is ordered such that the grade corresponds
      to its matching weight above."
    [:br]
    (text-area {:rows 15 :cols 30 :placeholder
"[89 78 63]
                    [78 91 60]
                    [87 65 79]
                    ... " } "grades" grades)]
     (submit-button "process"))]))

(defn processed [weights grades]
  (cond
   (empty? weights)
   (home weights grades "You forgot to add the weights!")
   (empty? grades)
   (home weights grades "You forgot to add the grades!")
  :else
  (do
  (html  
   [:h2 "These are your final grades."]
   [:hr]
   [:p "test"]))))  ;; <- I would like to call process-grades here. "test" renders fine. 

(defroutes app
  (GET "/" []
       {:status 200
        :headers {"Content-Type" "text/html"}
        :body (home)})
  (POST "/" [weights grades] (processed weights grades)) 
  (ANY "*" []
       (route/not-found (slurp (io/resource "404.html"))))) 

;; ... 
(定义工艺等级)
“将用户输入从home的表单转换为函数,并将其处理到最终成绩列表中”
[重量等级]
(->)等级

(映射(部分百分比向量权重));在哪里
权重和
等级被传递到
处理的
中?我想如果你想使用它们,你需要将它们作为参数传递:

(defn processed [weights grades]
  ;; .. snip
  )

;; .. snip

(POST "/" [weights grades] (processed weights grades))

我的假设是正确的。我将您的代码放入一个裸骨luminus项目中。您的代码生成的html如下所示:

<h3>

Enter the weights for each of the grades below. Of…
<br></br>
<textarea id="weights" placeholder="[40 10 50] <- adds up to 100%" name="weights" cols="30"></textarea>
</h3>
<h3>
Enter ALL of the grades for EACH STUDENT in your c…
<br></br>
<textarea id="grades" rows="15" placeholder="bla" name="grades" cols="30"></textarea>
</h3>

输入以下每个等级的权重。共…


在你的课程中输入每个学生的所有分数…

错误来了:

<form method="POST" action="/">
    <input type="submit" value="process"></input>
</form>

表单元素必须包装输入元素,否则它不会将它们作为请求的一部分提交

因此,如果您将hiccup代码更改为:

(defn home [ & [weights grades error]]
  (html
    [:h1 "Welcome to Clojure-grade"]
    [:p error]
    [:hr]
    (form-to [:post "/"]
      [:h3 "Enter the weights for each of the grades below. Of course, all of the numbers should add up to 100%. Be sure to include the brackets"
     [:br]
     (text-area {:cols 30 :placeholder "[40 10 50] <- adds up to 100%"} "weights" weights)
     ]
    [:h3 "Enter ALL of the grades for EACH STUDENT in your class.
      Make sure that each of the grades is ordered such that the grade corresponds
      to its matching weight above."
     [:br]
     (text-area {:rows 15 :cols 30 :placeholder "bla"} "grades" grades)]
                                       ;...
                                       ;
                                       ;                                     (Each     grade corresponds to one of the weights above,
                                       ; so order is important. You can copy and paste directly from your excel file but don't forget
                                       ; the brackets!)" } "grades" grades)]
     (submit-button "process")))) ;; <- when I hit this in the browser I get a 404, with or without input.
(defn home[&[weights grades error]]
(html
[:h1“欢迎来到Clojure年级”]
[:p错误]
[:hr]
(表格至[:post/“]
[:h3“输入以下每个等级的权重。当然,所有数字的总和应为100%。确保包括括号”
[:br]

(文本区域{:cols 30:占位符“[40 10 50]我尝试过这个方法,但是我得到了一个404,它正在访问另一个文件夹中的html,这意味着它完全跳过了“POST”方法。我还向“processed”函数添加了一些异常捕获,以测试它是否被调用,并更改了数学位,以查看是否可以使其呈现文本。Ne它已经成功了。home函数应该定义用户输入的权重和等级变量,然后对它们进行处理。我将编辑上面的代码,向您展示此文件中的所有内容。谢谢您的帮助!只是调试的一般思路。您是否向firebug检查post请求?值是否如预期的那样?您是否检查了基因分级html表单?看起来正确吗?可能只是某个地方有一个简单的语法/拼写错误。我不熟悉hiccup,但我看不到“等级”“在某个地方定义了输入,也许这就是问题所在?我会研究firebug,但没有呈现html,只有404错误页面。我认为权重和等级变量是通过home函数中的文本区域标记定义的,带有“权重”权重和“等级”分数,但我必须承认,这种语法让人困惑。hiccup文档的信息量也不多,谷歌搜索发现了我的问题,并发布了过时的博客文章。在compojure文档中,我看到了一些我认为可能有用的东西,但它超出了我的理解范围(POST/“[weights grades]”…)看起来不正确。您的URI中没有参数,它只是“/”。如果它没有被命中,您可能实际上没有向/发送POST请求。如果没有参数,那么应该如何从URI中提取权重和分数?我认为您可能需要从请求参数而不是URI中提取权重和分数。在我看来,您的问题是“为什么我会出现404错误?”,而不是“我需要一个数据库吗?“你对表单功能的看法是正确的,但它仍然不起作用。我认为在它真正运行之前,我有很多疑难解答要做。我在google组中启动了一个线程,因为它似乎变得太难用了。不管你想要什么:D我在这里上传了我的工作示例:你可以检查它并使用它运行“lein ring server”,转到localhost:3000/landing,输入您的输入,提交后,您将在控制台输出中看到数据。顺便说一句,使用luminus之类的工具将使您更容易开始;-)由于您上一篇文章,我完全弄清楚了路由。一些见解:(1)我们可以简单地在defroutes中实现get“/landing”/“(2)我的应用程序一直在clojuregrade.web命名空间中运行。通过在我的defroutes中添加帖子,我可以复制您所做的操作。(3)将输入数据结构转换为process grades函数可读的内容是一个非常棘手的问题,可能是一个新问题。我想我已经完成了这个
lein new heroku
模板。Luminus似乎是新的标准,并且有更好的文档记录。再次感谢!是的,只需使用通过luminus和代码,重要的部分很容易理解。稍后您仍然可以使用heroku模板。如果您掌握了基本部分,您将看到luminus只是由“标准clojure web应用程序”组成。