1use crate::FormError;
7use crate::formset::FormSet;
8use crate::model_form::{FormModel, ModelForm};
9use std::marker::PhantomData;
10
11pub struct InlineFormSet<P: FormModel, C: FormModel> {
16 parent: P,
17 _formset: FormSet,
18 fk_field: String,
19 child_forms: Vec<ModelForm<C>>,
20 _phantom_parent: PhantomData<P>,
21 _phantom_child: PhantomData<C>,
22}
23
24impl<P: FormModel, C: FormModel> InlineFormSet<P, C> {
25 pub fn new(parent: P, fk_field: String) -> Self {
39 Self {
40 parent,
41 _formset: FormSet::new("inline".to_string()),
42 fk_field,
43 child_forms: Vec::new(),
44 _phantom_parent: PhantomData,
45 _phantom_child: PhantomData,
46 }
47 }
48
49 pub fn add_child_form(&mut self, form: ModelForm<C>) {
51 self.child_forms.push(form);
52 }
53
54 pub fn parent(&self) -> &P {
56 &self.parent
57 }
58
59 pub fn fk_field(&self) -> &str {
61 &self.fk_field
62 }
63
64 pub fn child_forms(&self) -> &[ModelForm<C>] {
66 &self.child_forms
67 }
68
69 pub fn save(&mut self) -> Result<(), FormError> {
79 self.parent
81 .save()
82 .map_err(|e| FormError::Validation(format!("Failed to save parent: {}", e)))?;
83
84 let parent_id = self.parent.get_field("id").ok_or_else(|| {
86 FormError::Validation("Parent model does not have an 'id' field".to_string())
87 })?;
88
89 let fk_field = self.fk_field.clone();
91 for child_form in &mut self.child_forms {
92 child_form.set_field_value(&fk_field, parent_id.clone());
94
95 child_form
96 .save()
97 .map_err(|e| FormError::Validation(format!("Failed to save child: {}", e)))?;
98 }
99
100 Ok(())
101 }
102
103 pub fn is_valid(&mut self) -> bool {
105 let mut all_valid = true;
106
107 for child_form in &mut self.child_forms {
108 if !child_form.is_valid() {
109 all_valid = false;
110 }
111 }
112
113 all_valid
114 }
115}
116
117pub struct ModelFormSet<T: FormModel> {
121 forms: Vec<ModelForm<T>>,
122 prefix: String,
123 can_delete: bool,
124 can_order: bool,
125 extra: usize,
126 max_num: Option<usize>,
127 min_num: usize,
128 errors: Vec<String>,
129 _phantom: PhantomData<T>,
130}
131
132impl<T: FormModel> ModelFormSet<T> {
133 pub fn new(prefix: String) -> Self {
141 Self {
142 forms: Vec::new(),
143 prefix,
144 can_delete: false,
145 can_order: false,
146 extra: 1,
147 max_num: Some(1000),
148 min_num: 0,
149 errors: Vec::new(),
150 _phantom: PhantomData,
151 }
152 }
153
154 pub fn with_extra(mut self, extra: usize) -> Self {
156 self.extra = extra;
157 self
158 }
159
160 pub fn with_can_delete(mut self, can_delete: bool) -> Self {
162 self.can_delete = can_delete;
163 self
164 }
165
166 pub fn with_can_order(mut self, can_order: bool) -> Self {
168 self.can_order = can_order;
169 self
170 }
171
172 pub fn with_max_num(mut self, max_num: Option<usize>) -> Self {
174 self.max_num = max_num;
175 self
176 }
177
178 pub fn with_min_num(mut self, min_num: usize) -> Self {
180 self.min_num = min_num;
181 self
182 }
183
184 pub fn add_form(&mut self, form: ModelForm<T>) -> Result<(), String> {
188 if let Some(max) = self.max_num
189 && self.forms.len() >= max
190 {
191 return Err(format!(
192 "Cannot add form: maximum number of forms ({}) reached",
193 max
194 ));
195 }
196 self.forms.push(form);
197 Ok(())
198 }
199
200 pub fn forms(&self) -> &[ModelForm<T>] {
202 &self.forms
203 }
204
205 pub fn forms_mut(&mut self) -> &mut Vec<ModelForm<T>> {
207 &mut self.forms
208 }
209
210 pub fn is_valid(&mut self) -> bool {
212 self.errors.clear();
213
214 let mut all_valid = true;
215 for form in &mut self.forms {
216 if !form.is_valid() {
217 all_valid = false;
218 }
219 }
220
221 if self.forms.len() < self.min_num {
223 self.errors
224 .push(format!("Please submit at least {} forms", self.min_num));
225 all_valid = false;
226 }
227
228 if let Some(max) = self.max_num
230 && self.forms.len() > max
231 {
232 self.errors
233 .push(format!("Please submit no more than {} forms", max));
234 all_valid = false;
235 }
236
237 all_valid
238 }
239
240 pub fn errors(&self) -> &[String] {
242 &self.errors
243 }
244
245 pub fn save(&mut self) -> Result<(), FormError> {
247 if !self.is_valid() {
248 return Err(FormError::Validation(
249 "Cannot save invalid formset".to_string(),
250 ));
251 }
252
253 for form in &mut self.forms {
254 form.save()
255 .map_err(|e| FormError::Validation(format!("Failed to save form: {}", e)))?;
256 }
257
258 Ok(())
259 }
260
261 pub fn prefix(&self) -> &str {
263 &self.prefix
264 }
265}
266
267pub struct FormSetFactory {
272 prefix: String,
273 extra: usize,
274 can_delete: bool,
275 can_order: bool,
276 max_num: Option<usize>,
277 min_num: usize,
278}
279
280impl FormSetFactory {
281 pub fn new(prefix: String) -> Self {
292 Self {
293 prefix,
294 extra: 1,
295 can_delete: false,
296 can_order: false,
297 max_num: Some(1000),
298 min_num: 0,
299 }
300 }
301
302 pub fn with_extra(mut self, extra: usize) -> Self {
314 self.extra = extra;
315 self
316 }
317
318 pub fn with_can_delete(mut self, can_delete: bool) -> Self {
330 self.can_delete = can_delete;
331 self
332 }
333
334 pub fn with_can_order(mut self, can_order: bool) -> Self {
346 self.can_order = can_order;
347 self
348 }
349
350 pub fn with_max_num(mut self, max_num: Option<usize>) -> Self {
362 self.max_num = max_num;
363 self
364 }
365
366 pub fn with_min_num(mut self, min_num: usize) -> Self {
378 self.min_num = min_num;
379 self
380 }
381
382 pub fn extra(&self) -> usize {
384 self.extra
385 }
386
387 pub fn can_delete(&self) -> bool {
389 self.can_delete
390 }
391
392 pub fn can_order(&self) -> bool {
394 self.can_order
395 }
396
397 pub fn max_num(&self) -> Option<usize> {
399 self.max_num
400 }
401
402 pub fn min_num(&self) -> usize {
404 self.min_num
405 }
406
407 pub fn create(&self) -> FormSet {
423 FormSet::new(self.prefix.clone())
424 .with_extra(self.extra)
425 .with_can_delete(self.can_delete)
426 .with_can_order(self.can_order)
427 .with_max_num(self.max_num)
428 .with_min_num(self.min_num)
429 }
430
431 pub fn create_model_formset<T: FormModel>(&self) -> ModelFormSet<T> {
444 ModelFormSet::new(self.prefix.clone())
445 .with_extra(self.extra)
446 .with_can_delete(self.can_delete)
447 .with_can_order(self.can_order)
448 .with_max_num(self.max_num)
449 .with_min_num(self.min_num)
450 }
451}
452
453#[cfg(test)]
454mod tests {
455 use super::*;
456 use crate::ModelFormConfig;
457 use crate::model_form::FieldType;
458 use serde_json::Value;
459
460 #[derive(Clone)]
462 struct TestModel {
463 id: Option<i64>,
464 name: String,
465 email: String,
466 }
467
468 impl FormModel for TestModel {
469 fn field_names() -> Vec<String> {
470 vec!["id".to_string(), "name".to_string(), "email".to_string()]
471 }
472
473 fn field_type(name: &str) -> Option<FieldType> {
474 match name {
475 "id" => Some(FieldType::Integer),
476 "name" => Some(FieldType::Char {
477 max_length: Some(100),
478 }),
479 "email" => Some(FieldType::Email),
480 _ => None,
481 }
482 }
483
484 fn get_field(&self, name: &str) -> Option<Value> {
485 match name {
486 "id" => self.id.map(|id| Value::Number(id.into())),
487 "name" => Some(Value::String(self.name.clone())),
488 "email" => Some(Value::String(self.email.clone())),
489 _ => None,
490 }
491 }
492
493 fn set_field(&mut self, name: &str, value: Value) -> Result<(), String> {
494 match name {
495 "id" => {
496 self.id = value.as_i64();
497 Ok(())
498 }
499 "name" => {
500 self.name = value
501 .as_str()
502 .ok_or("Expected string for name")?
503 .to_string();
504 Ok(())
505 }
506 "email" => {
507 self.email = value
508 .as_str()
509 .ok_or("Expected string for email")?
510 .to_string();
511 Ok(())
512 }
513 _ => Err(format!("Unknown field: {}", name)),
514 }
515 }
516
517 fn save(&mut self) -> Result<(), String> {
518 if self.id.is_none() {
519 self.id = Some(1);
520 }
521 Ok(())
522 }
523 }
524
525 #[derive(Clone)]
527 struct ChildModel {
528 id: Option<i64>,
529 parent_id: Option<i64>,
530 content: String,
531 }
532
533 impl FormModel for ChildModel {
534 fn field_names() -> Vec<String> {
535 vec![
536 "id".to_string(),
537 "parent_id".to_string(),
538 "content".to_string(),
539 ]
540 }
541
542 fn field_type(name: &str) -> Option<FieldType> {
543 match name {
544 "id" | "parent_id" => Some(FieldType::Integer),
545 "content" => Some(FieldType::Text),
546 _ => None,
547 }
548 }
549
550 fn get_field(&self, name: &str) -> Option<Value> {
551 match name {
552 "id" => self.id.map(|id| Value::Number(id.into())),
553 "parent_id" => self.parent_id.map(|id| Value::Number(id.into())),
554 "content" => Some(Value::String(self.content.clone())),
555 _ => None,
556 }
557 }
558
559 fn set_field(&mut self, name: &str, value: Value) -> Result<(), String> {
560 match name {
561 "id" => {
562 self.id = value.as_i64();
563 Ok(())
564 }
565 "parent_id" => {
566 self.parent_id = value.as_i64();
567 Ok(())
568 }
569 "content" => {
570 self.content = value
571 .as_str()
572 .ok_or("Expected string for content")?
573 .to_string();
574 Ok(())
575 }
576 _ => Err(format!("Unknown field: {}", name)),
577 }
578 }
579
580 fn save(&mut self) -> Result<(), String> {
581 if self.id.is_none() {
582 self.id = Some(1);
583 }
584 Ok(())
585 }
586 }
587
588 #[test]
589 fn test_inline_formset_creation() {
590 let parent = TestModel {
591 id: Some(1),
592 name: "Parent".to_string(),
593 email: "parent@example.com".to_string(),
594 };
595
596 let formset = InlineFormSet::<TestModel, ChildModel>::new(parent, "parent_id".to_string());
597
598 assert_eq!(formset.fk_field(), "parent_id");
599 assert_eq!(formset.parent().name, "Parent");
600 assert_eq!(formset.child_forms().len(), 0);
601 }
602
603 #[test]
604 fn test_inline_formset_add_child() {
605 let parent = TestModel {
606 id: Some(1),
607 name: "Parent".to_string(),
608 email: "parent@example.com".to_string(),
609 };
610
611 let mut formset =
612 InlineFormSet::<TestModel, ChildModel>::new(parent, "parent_id".to_string());
613
614 let child = ChildModel {
615 id: None,
616 parent_id: None,
617 content: "Child content".to_string(),
618 };
619 let child_form = ModelForm::new(Some(child), ModelFormConfig::new());
620 formset.add_child_form(child_form);
621
622 assert_eq!(formset.child_forms().len(), 1);
623 }
624
625 #[test]
626 fn test_inline_formset_save() {
627 let parent = TestModel {
628 id: Some(1),
629 name: "Parent".to_string(),
630 email: "parent@example.com".to_string(),
631 };
632
633 let mut formset =
634 InlineFormSet::<TestModel, ChildModel>::new(parent, "parent_id".to_string());
635
636 let child = ChildModel {
637 id: None,
638 parent_id: None,
639 content: "Child content".to_string(),
640 };
641 let child_form = ModelForm::new(Some(child), ModelFormConfig::new());
642 formset.add_child_form(child_form);
643
644 let result = formset.save();
645 assert!(result.is_ok());
646 }
647
648 #[test]
649 fn test_model_formset_creation() {
650 let formset = ModelFormSet::<TestModel>::new("test".to_string());
651
652 assert_eq!(formset.prefix(), "test");
653 assert_eq!(formset.forms().len(), 0);
654 assert!(!formset.can_delete);
655 assert!(!formset.can_order);
656 }
657
658 #[test]
659 fn test_model_formset_add_form() {
660 let mut formset = ModelFormSet::<TestModel>::new("test".to_string());
661
662 let instance = TestModel {
663 id: None,
664 name: "Test".to_string(),
665 email: "test@example.com".to_string(),
666 };
667 let form = ModelForm::new(Some(instance), ModelFormConfig::new());
668 formset.add_form(form).unwrap();
669
670 assert_eq!(formset.forms().len(), 1);
671 }
672
673 #[test]
674 fn test_model_formset_validation() {
675 let mut formset = ModelFormSet::<TestModel>::new("test".to_string())
676 .with_min_num(2)
677 .with_max_num(Some(5));
678
679 let instance = TestModel {
680 id: None,
681 name: "Test".to_string(),
682 email: "test@example.com".to_string(),
683 };
684 let form = ModelForm::new(Some(instance), ModelFormConfig::new());
685 formset.add_form(form).unwrap();
686
687 assert!(!formset.is_valid());
688 assert!(!formset.errors().is_empty());
689 }
690
691 #[test]
692 fn test_formset_factory_creation() {
693 let factory = FormSetFactory::new("form".to_string());
694
695 assert_eq!(factory.extra(), 1);
696 assert!(!factory.can_delete());
697 assert!(!factory.can_order());
698 assert_eq!(factory.max_num(), Some(1000));
699 assert_eq!(factory.min_num(), 0);
700 }
701
702 #[test]
703 fn test_formset_factory_builder() {
704 let factory = FormSetFactory::new("form".to_string())
705 .with_extra(3)
706 .with_can_delete(true)
707 .with_can_order(true)
708 .with_max_num(Some(10))
709 .with_min_num(2);
710
711 assert_eq!(factory.extra(), 3);
712 assert!(factory.can_delete());
713 assert!(factory.can_order());
714 assert_eq!(factory.max_num(), Some(10));
715 assert_eq!(factory.min_num(), 2);
716 }
717
718 #[test]
719 fn test_formset_factory_create() {
720 let factory = FormSetFactory::new("form".to_string())
721 .with_extra(3)
722 .with_can_delete(true);
723
724 let formset = factory.create();
725
726 assert_eq!(formset.prefix(), "form");
727 assert!(formset.can_delete());
728 }
729
730 #[test]
731 fn test_formset_factory_create_model_formset() {
732 let factory = FormSetFactory::new("user".to_string())
733 .with_extra(2)
734 .with_min_num(1);
735
736 let formset = factory.create_model_formset::<TestModel>();
737
738 assert_eq!(formset.prefix(), "user");
739 assert_eq!(formset.min_num, 1);
740 }
741}