1use crate::Widget;
4use crate::field::{FieldError, FieldResult, FormField};
5use crate::model_form::FormModel;
6use serde_json::Value;
7use std::collections::HashMap;
8use std::marker::PhantomData;
9
10pub struct ModelChoiceField<T: FormModel> {
14 pub name: String,
16 pub required: bool,
18 pub error_messages: HashMap<String, String>,
20 pub widget: Widget,
22 pub help_text: String,
24 pub initial: Option<Value>,
26 pub queryset: Vec<T>,
28 pub empty_label: Option<String>,
30 _phantom: PhantomData<T>,
31}
32
33impl<T: FormModel> ModelChoiceField<T> {
34 pub fn new(name: impl Into<String>, queryset: Vec<T>) -> Self {
84 let mut error_messages = HashMap::new();
85 error_messages.insert(
86 "required".to_string(),
87 "This field is required.".to_string(),
88 );
89 error_messages.insert(
90 "invalid_choice".to_string(),
91 "Select a valid choice.".to_string(),
92 );
93
94 Self {
95 name: name.into(),
96 required: true,
97 error_messages,
98 widget: Widget::Select {
99 choices: Vec::new(),
100 },
101 help_text: String::new(),
102 initial: None,
103 queryset,
104 empty_label: Some("--------".to_string()),
105 _phantom: PhantomData,
106 }
107 }
108 pub fn required(mut self, required: bool) -> Self {
110 self.required = required;
111 self
112 }
113 pub fn help_text(mut self, text: impl Into<String>) -> Self {
115 self.help_text = text.into();
116 self
117 }
118 pub fn initial(mut self, value: Value) -> Self {
120 self.initial = Some(value);
121 self
122 }
123 pub fn empty_label(mut self, label: Option<String>) -> Self {
125 self.empty_label = label;
126 self
127 }
128 pub fn error_message(
130 mut self,
131 error_type: impl Into<String>,
132 message: impl Into<String>,
133 ) -> Self {
134 self.error_messages
135 .insert(error_type.into(), message.into());
136 self
137 }
138
139 #[allow(dead_code)]
143 fn get_choices(&self) -> Vec<(String, String)> {
144 let mut choices = Vec::new();
145
146 if !self.required && self.empty_label.is_some() {
147 choices.push(("".to_string(), self.empty_label.clone().unwrap()));
148 }
149
150 for instance in &self.queryset {
152 let value = instance.to_choice_value();
153 let label = instance.to_choice_label();
154 choices.push((value, label));
155 }
156
157 choices
158 }
159}
160
161impl<T: FormModel> FormField for ModelChoiceField<T> {
162 fn name(&self) -> &str {
163 &self.name
164 }
165
166 fn label(&self) -> Option<&str> {
167 None
168 }
169
170 fn widget(&self) -> &Widget {
171 &self.widget
172 }
173
174 fn required(&self) -> bool {
175 self.required
176 }
177
178 fn initial(&self) -> Option<&Value> {
179 self.initial.as_ref()
180 }
181
182 fn help_text(&self) -> Option<&str> {
183 if self.help_text.is_empty() {
184 None
185 } else {
186 Some(&self.help_text)
187 }
188 }
189
190 fn clean(&self, value: Option<&Value>) -> FieldResult<Value> {
191 if value.is_none() || value == Some(&Value::Null) {
192 if self.required {
193 let error_msg = self
194 .error_messages
195 .get("required")
196 .cloned()
197 .unwrap_or_else(|| "This field is required.".to_string());
198 return Err(FieldError::validation(None, &error_msg));
199 }
200 return Ok(Value::Null);
201 }
202
203 let s = match value.unwrap() {
204 Value::String(s) => s.as_str(),
205 Value::Number(n) => {
206 &n.to_string()
208 }
209 _ => {
210 let error_msg = self
211 .error_messages
212 .get("invalid_choice")
213 .cloned()
214 .unwrap_or_else(|| "Select a valid choice.".to_string());
215 return Err(FieldError::validation(None, &error_msg));
216 }
217 };
218
219 if s.is_empty() {
220 if self.required {
221 let error_msg = self
222 .error_messages
223 .get("required")
224 .cloned()
225 .unwrap_or_else(|| "This field is required.".to_string());
226 return Err(FieldError::validation(None, &error_msg));
227 }
228 return Ok(Value::Null);
229 }
230
231 let choice_exists = self
233 .queryset
234 .iter()
235 .any(|instance| instance.to_choice_value() == s);
236
237 if !choice_exists {
238 let error_msg = self
239 .error_messages
240 .get("invalid_choice")
241 .cloned()
242 .unwrap_or_else(|| "Select a valid choice.".to_string());
243 return Err(FieldError::validation(None, &error_msg));
244 }
245
246 Ok(Value::String(s.to_string()))
247 }
248
249 fn has_changed(&self, initial: Option<&Value>, data: Option<&Value>) -> bool {
250 match (initial, data) {
251 (None, None) => false,
252 (Some(_), None) | (None, Some(_)) => true,
253 (Some(a), Some(b)) => a != b,
254 }
255 }
256}
257
258pub struct ModelMultipleChoiceField<T: FormModel> {
262 pub name: String,
264 pub required: bool,
266 pub error_messages: HashMap<String, String>,
268 pub widget: Widget,
270 pub help_text: String,
272 pub initial: Option<Value>,
274 pub queryset: Vec<T>,
276 _phantom: PhantomData<T>,
277}
278
279impl<T: FormModel> ModelMultipleChoiceField<T> {
280 pub fn new(name: impl Into<String>, queryset: Vec<T>) -> Self {
335 let mut error_messages = HashMap::new();
336 error_messages.insert(
337 "required".to_string(),
338 "This field is required.".to_string(),
339 );
340 error_messages.insert(
341 "invalid_choice".to_string(),
342 "Select a valid choice.".to_string(),
343 );
344 error_messages.insert(
345 "invalid_list".to_string(),
346 "Enter a list of values.".to_string(),
347 );
348
349 Self {
350 name: name.into(),
351 required: true,
352 error_messages,
353 widget: Widget::Select {
354 choices: Vec::new(),
355 },
356 help_text: String::new(),
357 initial: None,
358 queryset,
359 _phantom: PhantomData,
360 }
361 }
362 pub fn required(mut self, required: bool) -> Self {
364 self.required = required;
365 self
366 }
367 pub fn help_text(mut self, text: impl Into<String>) -> Self {
369 self.help_text = text.into();
370 self
371 }
372 pub fn initial(mut self, value: Value) -> Self {
374 self.initial = Some(value);
375 self
376 }
377 pub fn error_message(
379 mut self,
380 error_type: impl Into<String>,
381 message: impl Into<String>,
382 ) -> Self {
383 self.error_messages
384 .insert(error_type.into(), message.into());
385 self
386 }
387
388 #[allow(dead_code)]
391 fn get_choices(&self) -> Vec<(String, String)> {
392 let mut choices = Vec::new();
393
394 for instance in &self.queryset {
396 let value = instance.to_choice_value();
397 let label = instance.to_choice_label();
398 choices.push((value, label));
399 }
400
401 choices
402 }
403}
404
405impl<T: FormModel> FormField for ModelMultipleChoiceField<T> {
406 fn name(&self) -> &str {
407 &self.name
408 }
409
410 fn label(&self) -> Option<&str> {
411 None
412 }
413
414 fn widget(&self) -> &Widget {
415 &self.widget
416 }
417
418 fn required(&self) -> bool {
419 self.required
420 }
421
422 fn initial(&self) -> Option<&Value> {
423 self.initial.as_ref()
424 }
425
426 fn help_text(&self) -> Option<&str> {
427 if self.help_text.is_empty() {
428 None
429 } else {
430 Some(&self.help_text)
431 }
432 }
433
434 fn clean(&self, value: Option<&Value>) -> FieldResult<Value> {
435 if value.is_none() || value == Some(&Value::Null) {
436 if self.required {
437 let error_msg = self
438 .error_messages
439 .get("required")
440 .cloned()
441 .unwrap_or_else(|| "This field is required.".to_string());
442 return Err(FieldError::validation(None, &error_msg));
443 }
444 return Ok(Value::Array(Vec::new()));
445 }
446
447 let values = match value.unwrap() {
448 Value::Array(arr) => arr.clone(),
449 Value::String(s) if s.is_empty() => {
450 if self.required {
451 let error_msg = self
452 .error_messages
453 .get("required")
454 .cloned()
455 .unwrap_or_else(|| "This field is required.".to_string());
456 return Err(FieldError::validation(None, &error_msg));
457 }
458 return Ok(Value::Array(Vec::new()));
459 }
460 Value::String(s) => {
461 s.split(',')
463 .map(|v| Value::String(v.trim().to_string()))
464 .collect()
465 }
466 _ => {
467 let error_msg = self
468 .error_messages
469 .get("invalid_list")
470 .cloned()
471 .unwrap_or_else(|| "Enter a list of values.".to_string());
472 return Err(FieldError::validation(None, &error_msg));
473 }
474 };
475
476 if values.is_empty() && self.required {
477 let error_msg = self
478 .error_messages
479 .get("required")
480 .cloned()
481 .unwrap_or_else(|| "This field is required.".to_string());
482 return Err(FieldError::validation(None, &error_msg));
483 }
484
485 for value in &values {
487 if let Some(value_str) = value.as_str() {
488 let choice_exists = self
489 .queryset
490 .iter()
491 .any(|instance| instance.to_choice_value() == value_str);
492
493 if !choice_exists {
494 let error_msg = self
495 .error_messages
496 .get("invalid_choice")
497 .cloned()
498 .unwrap_or_else(|| format!("'{}' is not a valid choice.", value_str));
499 return Err(FieldError::validation(None, &error_msg));
500 }
501 }
502 }
503
504 Ok(Value::Array(values))
505 }
506
507 fn has_changed(&self, initial: Option<&Value>, data: Option<&Value>) -> bool {
508 match (initial, data) {
509 (None, None) => false,
510 (Some(_), None) | (None, Some(_)) => true,
511 (Some(Value::Array(a)), Some(Value::Array(b))) => {
512 if a.len() != b.len() {
513 return true;
514 }
515 a.iter().zip(b.iter()).any(|(x, y)| x != y)
516 }
517 (Some(a), Some(b)) => a != b,
518 }
519 }
520}
521
522#[cfg(test)]
523mod tests {
524 use super::*;
525 use crate::FormField;
526 use serde_json::json;
527
528 struct TestModel {
530 id: i32,
531 name: String,
532 }
533
534 impl FormModel for TestModel {
535 fn field_names() -> Vec<String> {
536 vec!["id".to_string(), "name".to_string()]
537 }
538
539 fn get_field(&self, name: &str) -> Option<Value> {
540 match name {
541 "id" => Some(Value::Number(self.id.into())),
542 "name" => Some(Value::String(self.name.clone())),
543 _ => None,
544 }
545 }
546
547 fn set_field(&mut self, _name: &str, _value: Value) -> Result<(), String> {
548 Ok(())
549 }
550
551 fn save(&mut self) -> Result<(), String> {
552 Ok(())
553 }
554 }
555
556 #[test]
557 fn test_model_choice_field_basic() {
558 let queryset = vec![
559 TestModel {
560 id: 1,
561 name: "Option 1".to_string(),
562 },
563 TestModel {
564 id: 2,
565 name: "Option 2".to_string(),
566 },
567 ];
568
569 let field = ModelChoiceField::new("choice", queryset);
570
571 assert_eq!(field.name(), "choice");
572 assert!(FormField::required(&field));
573 }
574
575 #[test]
576 fn test_model_choice_field_required() {
577 let field = ModelChoiceField::new("choice", Vec::<TestModel>::new());
578
579 let result = field.clean(None);
580 assert!(result.is_err());
581 }
582
583 #[test]
584 fn test_model_choice_field_not_required() {
585 let field = ModelChoiceField::new("choice", Vec::<TestModel>::new()).required(false);
586
587 let result = field.clean(None);
588 assert!(result.is_ok());
589 assert_eq!(result.unwrap(), Value::Null);
590 }
591
592 #[test]
593 fn test_model_multiple_choice_field_basic() {
594 let queryset = vec![
595 TestModel {
596 id: 1,
597 name: "Option 1".to_string(),
598 },
599 TestModel {
600 id: 2,
601 name: "Option 2".to_string(),
602 },
603 ];
604
605 let field = ModelMultipleChoiceField::new("choices", queryset);
606
607 assert_eq!(field.name(), "choices");
608 assert!(FormField::required(&field));
609 }
610
611 #[test]
612 fn test_model_multiple_choice_field_array() {
613 let queryset = vec![
614 TestModel {
615 id: 1,
616 name: "Option 1".to_string(),
617 },
618 TestModel {
619 id: 2,
620 name: "Option 2".to_string(),
621 },
622 TestModel {
623 id: 3,
624 name: "Option 3".to_string(),
625 },
626 ];
627
628 let field = ModelMultipleChoiceField::new("choices", queryset).required(false);
629
630 let result = field.clean(Some(&json!(["1", "2"])));
631 assert!(result.is_ok());
632
633 if let Value::Array(arr) = result.unwrap() {
634 assert_eq!(arr.len(), 2);
635 } else {
636 panic!("Expected array");
637 }
638 }
639
640 #[test]
641 fn test_model_multiple_choice_field_comma_separated() {
642 let queryset = vec![
643 TestModel {
644 id: 1,
645 name: "Option 1".to_string(),
646 },
647 TestModel {
648 id: 2,
649 name: "Option 2".to_string(),
650 },
651 TestModel {
652 id: 3,
653 name: "Option 3".to_string(),
654 },
655 ];
656
657 let field = ModelMultipleChoiceField::new("choices", queryset).required(false);
658
659 let result = field.clean(Some(&json!("1,2,3")));
660 assert!(result.is_ok());
661
662 if let Value::Array(arr) = result.unwrap() {
663 assert_eq!(arr.len(), 3);
664 } else {
665 panic!("Expected array");
666 }
667 }
668}