如何使用elixir/phoenix从csv文件导入用户?

如何使用elixir/phoenix从csv文件导入用户?,elixir,phoenix-framework,Elixir,Phoenix Framework,我有一个csv文件,其中包含用户列表和UserController中的以下导入方法,我希望通过提交csv文件和表单来导入这些用户。看起来我做错了 用户\u控制器 def import(conn, %{"user" => user_params}) do user_params["file"] |> File.stream!() |> CSV.decode |> Enum.each(fn(user) -> User.changese

我有一个csv文件,其中包含用户列表和UserController中的以下导入方法,我希望通过提交csv文件和表单来导入这些用户。看起来我做错了

用户\u控制器

  def import(conn, %{"user" => user_params}) do
    user_params["file"]
    |> File.stream!()
    |> CSV.decode
    |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end)
    conn
    |> put_flash(:info, "Imported")
    |> redirect(to: user_path(conn, :index))
  end
路线

post "/import", UsersController, :import, as: :import_csv
表格

<%= render "import_form.html", changeset: @changeset,
                        action: import_csv_path(@conn, :import) %>

以下代码适用于iex

  def import(file) do
    file
    |> File.stream!()
    |> CSV.decode
    |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end)
  end

你的params里没有文件。这是我为一个多部分文件返回的参数

[warn] module=UcxChat.AttachmentController line=10 function=create/2  attachment params: %{"channel_id" => "300233dd-782f-4718-9eed-00b8cc412a79", "description" => "", "file" => %Plug.Upload{content_type: "text/plain", filename: "test.txt", path: "/var/folders/wt/3q11kty15rqfb5v9rpqg0ssm0000gn/T//plug-1494/multipart-421483-239132-3"}, "file_name" => "test.txt", "type" => "text/plain", "user_id" => "427452eb-c9cf-457b-9c55-0904c9d24385"}
您可以看到
params[“file”]
是一个
Plug.upload
struct

要获取实际文件,您应该获得:path字段,如:

  def import(conn, %{"user" => user_params}) do
    user_params["file"].path
    |> File.stream!()
    |> CSV.decode
    |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end)
    conn
    |> put_flash(:info, "Imported")
    |> redirect(to: user_path(conn, :index))
  end
您可能还想做一些错误处理。比如:

def import(conn, %{"user" => user_params}) do
  user_params["file"].path
  |> File.stream!()
  |> CSV.decode
  |> Enum.map(fn(user) -> 
    User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert 
  end)
  |> Enum.filter(fn 
    {:error, cs} -> true
    _ -> false
  end)
  |> case do
    [] -> 
      conn
      |> put_flash(:info, "Imported")
      |> redirect(to: user_path(conn, :index))
    errors -> 
      errors = parse_errors(errors)  # create this fun 
      conn
      |> put_flash(:erorr, errors)
      |> render("import.html")
  end
end

你的params里没有文件。这是我为一个多部分文件返回的参数

[warn] module=UcxChat.AttachmentController line=10 function=create/2  attachment params: %{"channel_id" => "300233dd-782f-4718-9eed-00b8cc412a79", "description" => "", "file" => %Plug.Upload{content_type: "text/plain", filename: "test.txt", path: "/var/folders/wt/3q11kty15rqfb5v9rpqg0ssm0000gn/T//plug-1494/multipart-421483-239132-3"}, "file_name" => "test.txt", "type" => "text/plain", "user_id" => "427452eb-c9cf-457b-9c55-0904c9d24385"}
您可以看到
params[“file”]
是一个
Plug.upload
struct

要获取实际文件,您应该获得:path字段,如:

  def import(conn, %{"user" => user_params}) do
    user_params["file"].path
    |> File.stream!()
    |> CSV.decode
    |> Enum.each(fn(user) -> User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert end)
    conn
    |> put_flash(:info, "Imported")
    |> redirect(to: user_path(conn, :index))
  end
您可能还想做一些错误处理。比如:

def import(conn, %{"user" => user_params}) do
  user_params["file"].path
  |> File.stream!()
  |> CSV.decode
  |> Enum.map(fn(user) -> 
    User.changeset(%User{}, %{name: Enum.at(user, 0), email: Enum.at(user, 1)}) |> Repo.insert 
  end)
  |> Enum.filter(fn 
    {:error, cs} -> true
    _ -> false
  end)
  |> case do
    [] -> 
      conn
      |> put_flash(:info, "Imported")
      |> redirect(to: user_path(conn, :index))
    errors -> 
      errors = parse_errors(errors)  # create this fun 
      conn
      |> put_flash(:erorr, errors)
      |> render("import.html")
  end
end

您是否收到任何类型的错误?我在IO.chardata\u to\u string/1中没有得到匹配的函数子句,但是下面的答案解决了问题。我需要选择
路径
。TY您是否收到任何类型的错误?我在IO.chardata\u to\u string/1中没有得到匹配的函数子句,但下面的答案解决了问题。我需要选择
路径
。如果你不介意的话,这只是个小问题。在这种情况下,我真的需要使用变更集吗?我记得我试着用
form_来表示@conn,action
form,它给了我
assign@conn在eex模板中不可用。
谢谢你不确定你说的“在这种情况下我真的需要使用变更集”是什么意思?此外,如果您试图从一个分部使用
@conn
(从模板中调用
render
),则需要传递conn绑定
我的意思是不使用model抱歉,如果我太笨了,但我仍然没有跟上。你能详细说明一下吗?我已经解决了我的问题:)谢谢。现在我只是使用
%>
def import(conn,%%{“import\u csv”=>file})来执行
,所以我不为我的表单提供@changeset。如果你不介意的话,这只是一个小问题。在这种情况下,我真的需要使用变更集吗?我记得我试着用
form_来表示@conn,action
form,它给了我
assign@conn在eex模板中不可用。
谢谢你不确定你说的“在这种情况下我真的需要使用变更集”是什么意思?此外,如果您试图从一个分部使用
@conn
(从模板中调用
render
),则需要传递conn绑定
我的意思是不使用model抱歉,如果我太笨了,但我仍然没有跟上。你能详细说明一下吗?我已经解决了我的问题:)谢谢。现在我只使用
%>
def import(conn,%%{“import\u csv”=>file})do
,所以我不向表单提供@changeset。