switch to multipart form
This commit is contained in:
parent
a0fe692046
commit
5aa8bc809d
@ -5,6 +5,8 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "4.0.1"
|
actix-web = "4.0.1"
|
||||||
|
actix-multipart = "0.4.0"
|
||||||
|
futures-util = "0.3.21"
|
||||||
tera = "1.16.0"
|
tera = "1.16.0"
|
||||||
actix_admin_macros = { path = "actix_admin_macros" }
|
actix_admin_macros = { path = "actix_admin_macros" }
|
||||||
async-trait = "0.1.53"
|
async-trait = "0.1.53"
|
||||||
|
@ -67,7 +67,6 @@ pub fn get_html_input_type<S: BuildHasher>(value: &tera::Value, _: &HashMap<Stri
|
|||||||
Ok(to_value(html_input_type).unwrap())
|
Ok(to_value(html_input_type).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AppDataTrait
|
// AppDataTrait
|
||||||
pub trait ActixAdminAppDataTrait {
|
pub trait ActixAdminAppDataTrait {
|
||||||
fn get_db(&self) -> &DatabaseConnection;
|
fn get_db(&self) -> &DatabaseConnection;
|
||||||
|
@ -3,6 +3,8 @@ use async_trait::async_trait;
|
|||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use actix_multipart:: {Multipart, MultipartError} ;
|
||||||
|
use futures_util::stream::StreamExt as _;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait ActixAdminModelTrait {
|
pub trait ActixAdminModelTrait {
|
||||||
@ -27,29 +29,41 @@ pub struct ActixAdminModel {
|
|||||||
pub errors: HashMap<String, String>,
|
pub errors: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for ActixAdminModel {
|
impl ActixAdminModel {
|
||||||
fn from(string: String) -> Self {
|
pub fn create_empty() -> ActixAdminModel {
|
||||||
let mut hashmap = HashMap::new();
|
|
||||||
let key_values: Vec<&str> = string.split('&').collect();
|
|
||||||
for key_value in key_values {
|
|
||||||
if !key_value.is_empty() {
|
|
||||||
let mut iter = key_value.splitn(2, '=');
|
|
||||||
hashmap.insert(
|
|
||||||
iter.next().unwrap().to_string(),
|
|
||||||
iter.next().unwrap().to_string(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ActixAdminModel {
|
ActixAdminModel {
|
||||||
primary_key: None,
|
primary_key: None,
|
||||||
values: hashmap,
|
values: HashMap::new(),
|
||||||
errors: HashMap::new(),
|
errors: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl ActixAdminModel {
|
pub async fn create_from_payload(mut payload: Multipart) -> Result<ActixAdminModel, MultipartError> {
|
||||||
|
let mut hashmap = HashMap::<String, String>::new();
|
||||||
|
|
||||||
|
while let Some(item) = payload.next().await {
|
||||||
|
let mut field = item?;
|
||||||
|
|
||||||
|
// TODO: how to handle binary chunks?
|
||||||
|
while let Some(chunk) = field.next().await {
|
||||||
|
//println!("-- CHUNK: \n{:?}", String::from_utf8(chunk.map_or(Vec::new(), |c| c.to_vec())));
|
||||||
|
let res_string = String::from_utf8(chunk.map_or(Vec::new(), |c| c.to_vec()));
|
||||||
|
if res_string.is_ok() {
|
||||||
|
hashmap.insert(
|
||||||
|
field.name().to_string(),
|
||||||
|
res_string.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ActixAdminModel {
|
||||||
|
primary_key: None,
|
||||||
|
values: hashmap,
|
||||||
|
errors: HashMap::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_value<T: std::str::FromStr>(&self, key: &str, is_option_or_string: bool) -> Result<Option<T>, String> {
|
pub fn get_value<T: std::str::FromStr>(&self, key: &str, is_option_or_string: bool) -> Result<Option<T>, String> {
|
||||||
let value = self.values.get(key);
|
let value = self.values.get(key);
|
||||||
|
|
||||||
@ -60,6 +74,7 @@ impl ActixAdminModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let parsed_val = val.parse::<T>();
|
let parsed_val = val.parse::<T>();
|
||||||
|
println!("{:?}", val);
|
||||||
|
|
||||||
match parsed_val {
|
match parsed_val {
|
||||||
Ok(val) => Ok(Some(val)),
|
Ok(val) => Ok(Some(val)),
|
||||||
|
@ -9,10 +9,10 @@ pub async fn create_get<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
|||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
_body: web::Payload,
|
_body: web::Payload,
|
||||||
text: String,
|
_text: String,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
let model = ActixAdminModel::from(text);
|
let model = ActixAdminModel::create_empty();
|
||||||
|
|
||||||
create_or_edit_get::<T, E>(&data, db, model).await
|
create_or_edit_get::<T, E>(&data, db, model).await
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,17 @@ use actix_web::http::header;
|
|||||||
use actix_web::{web, error, Error, HttpRequest, HttpResponse};
|
use actix_web::{web, error, Error, HttpRequest, HttpResponse};
|
||||||
use tera::{Context};
|
use tera::{Context};
|
||||||
use crate::TERA;
|
use crate::TERA;
|
||||||
|
use actix_multipart::Multipart;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub async fn create_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
pub async fn create_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
text: String,
|
payload: Multipart,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
let mut model = ActixAdminModel::from(text);
|
let mut model = ActixAdminModel::create_from_payload(payload).await.unwrap();
|
||||||
model = E::create_entity(db, model).await;
|
model = E::create_entity(db, model).await;
|
||||||
|
|
||||||
create_or_edit_post::<T, E>(&data, db, model).await
|
create_or_edit_post::<T, E>(&data, db, model).await
|
||||||
@ -20,11 +21,11 @@ pub async fn create_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>
|
|||||||
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
pub async fn edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTrait>(
|
||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
data: web::Data<T>,
|
data: web::Data<T>,
|
||||||
text: String,
|
payload: Multipart,
|
||||||
id: web::Path<i32>
|
id: web::Path<i32>
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
let mut model = ActixAdminModel::from(text);
|
let mut model = ActixAdminModel::create_from_payload(payload).await.unwrap();
|
||||||
model = E::edit_entity(db, id.into_inner(), model).await;
|
model = E::edit_entity(db, id.into_inner(), model).await;
|
||||||
|
|
||||||
create_or_edit_post::<T, E>(&data, db, model).await
|
create_or_edit_post::<T, E>(&data, db, model).await
|
||||||
@ -35,6 +36,7 @@ async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTr
|
|||||||
let entity_names = &data.get_actix_admin().entity_names;
|
let entity_names = &data.get_actix_admin().entity_names;
|
||||||
let actix_admin = data.get_actix_admin();
|
let actix_admin = data.get_actix_admin();
|
||||||
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
let view_model = actix_admin.view_models.get(&entity_name).unwrap();
|
||||||
|
println!("{:?}", model);
|
||||||
|
|
||||||
if model.has_errors() {
|
if model.has_errors() {
|
||||||
let mut ctx = Context::new();
|
let mut ctx = Context::new();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form method="post">
|
<form method="post" enctype="multipart/form-data">
|
||||||
{% for model_field in view_model.fields -%}
|
{% for model_field in view_model.fields -%}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
|
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
|
||||||
|
BIN
database.db-wal
BIN
database.db-wal
Binary file not shown.
Loading…
Reference in New Issue
Block a user