[英]How to import users from csv file with elixir/phoenix?
我有一个包含用户列表的csv文件以及UserController中的以下导入方法,我想通过使用表单提交csv文件来导入这些用户。 而且看来我做错了。
users_controller
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) %>
--
<%= form_for @changeset, @action, [multipart: true], fn f -> %>
<div class="form-group">
<%= label f, :file, class: "control-label" %>
<%= file_input f, :file %>
</div>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
模型
schema "users" do
field :name, :string
field :email, :string
field :file, :any, virtual: true
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :email, :file])
|> validate_required([:name, :email])
|> unique_constraint(:email)
end
以下代码在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
您不会在参数中找到文件。 这是我得到的多部分文件的参数
[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
结构。
要获取实际文件,您应获取: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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.