Cannot update records from a PostgreSQL database. #2375
-
I have written the following code to update a This is the code I have so far, use actix_web::web::Json;
use actix_web::{patch, web, Error, HttpResponse, Responder};
use chrono::{NaiveDate, NaiveDateTime, NaiveTime, Utc};
use entity::user::Entity as User;
use sea_orm::{ActiveModelTrait, EntityTrait, IntoActiveModel};
use sea_orm::DatabaseConnection;
pub struct AppState {
pub db: DatabaseConnection,
}
#[derive(Serialize)]
pub struct ApiResponse {
pub message: String,
}
// this is the Entity
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize)]
#[sea_orm(table_name = "user")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub username: Option<String>,
pub firstname: Option<String>,
pub lastname: Option<String>,
#[sea_orm(unique)]
pub email: Option<String>,
pub password: Option<String>,
pub is_active: Option<bool>,
pub last_login: Option<DateTime>,
pub date_joined: Option<DateTime>,
pub created_at: Option<DateTime>,
pub updated_at: Option<DateTime>,
pub is_admin: Option<bool>,
pub is_superadmin: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct UserRequest {
pub username: Option<String>,
pub firstname: Option<String>,
pub lastname: Option<String>,
pub email: Option<String>,
pub password: Option<String>,
pub is_active: Option<bool>,
pub last_login: Option<NaiveDateTime>,
pub date_joined: Option<NaiveDateTime>,
pub created_at: Option<NaiveDateTime>,
pub updated_at: Option<NaiveDateTime>,
pub is_admin: Option<bool>,
pub is_superadmin: Option<bool>,
}
#[patch("/{id}")]
pub async fn update_user(id: web::Path<i32>, payload: Json<UserRequest>, app_state: web::Data<AppState>) -> Result<impl Responder, Error> {
let user_id = id.into_inner();
let result = User::find_by_id(user_id.clone()).one(&app_state.db).await;
match result {
Ok(model) => {
match model {
None => {
let message = format!("User with ID `{}`, does not exist", user_id.clone());
let response = ApiResponse { message };
Ok(HttpResponse::NotFound().json(response))
}
Some(mut user) => {
user.username = payload.username.clone().or(user.username);
user.firstname = payload.firstname.clone().or(user.firstname);
user.lastname = payload.lastname.clone().or(user.lastname);
user.email = payload.email.clone().or(user.email);
user.password = payload.password.clone().or(user.password);
user.is_active = Option::from(payload.is_active).or(user.is_active);
user.is_admin = Option::from(payload.is_admin).or(user.is_admin);
user.is_superadmin = Option::from(payload.is_superadmin).or(user.is_superadmin);
user.updated_at = Option::from(
NaiveDateTime::new(
NaiveDate::from(Utc::now().naive_utc()),
NaiveTime::from(Utc::now().time()),
)
);
println!("LOG: Update User: {:?}", user.clone());
let user_model = user.into_active_model();
println!("LOG: Update User: {:?}", user_model.clone());
// let result = User::update(user_model).exec(&app_state.db).await;
// this line has no effect on the database
let result = user_model.update(&app_state.db).await;
match result {
// json(response) returns existing un-modified row from database
Ok(response) => Ok(HttpResponse::Ok().json(response)),
Err(err) => {
let response = ApiResponse { message: err.to_string() };
Ok(HttpResponse::BadRequest().json(response))
}
}
}
}
}
Err(err) => {
let response = ApiResponse { message: err.to_string() };
Ok(HttpResponse::BadRequest().json(response))
}
}
} Example
{
"username": "koko",
"is_active": true
} But the response indicates no change has been applied to {
"id": 14,
"username": "cod",
"firstname": null,
"lastname": null,
"email": "cod@fi.sh",
"password": "123456",
"is_active": null,
"last_login": "1970-01-01T00:00:00",
"date_joined": null,
"created_at": null,
"updated_at": null,
"is_admin": false,
"is_superadmin": false
} Link to What am I doing wrong and how do I fix it? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
This really isn't the appropriate way to update a record. You are directly updating the model then entering an active model. You should be first entering an active model then performing your updates, like the docs illustrate. You must use The docs even emphasize this. Emphasis theirs:
|
Beta Was this translation helpful? Give feedback.
-
I am doing that, When I use user.username = Set(payload.username.clone()); I get this following error, Type mismatch [E0308]expected `String`, but found `ActiveValue<String>` |
Beta Was this translation helpful? Give feedback.
Reread the statement.
You are setting values on a
Model
not anActiveModel
as you are not first creating anActiveModel
. This is incorrect. You generally should not be modifying theModel
at all.Read the docs linked. They give a clear, proper example of exactly what you are trying to do.