Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/contrib/contenttypes/forms.py: 26%
40 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from django.contrib.contenttypes.models import ContentType
2from django.db import models
3from django.forms import ModelForm, modelformset_factory
4from django.forms.models import BaseModelFormSet
7class BaseGenericInlineFormSet(BaseModelFormSet):
8 """
9 A formset for generic inline objects to a parent.
10 """
12 def __init__(
13 self,
14 data=None,
15 files=None,
16 instance=None,
17 save_as_new=False,
18 prefix=None,
19 queryset=None,
20 **kwargs,
21 ):
22 opts = self.model._meta
23 self.instance = instance
24 self.rel_name = (
25 opts.app_label
26 + "-"
27 + opts.model_name
28 + "-"
29 + self.ct_field.name
30 + "-"
31 + self.ct_fk_field.name
32 )
33 self.save_as_new = save_as_new
34 if self.instance is None or self.instance.pk is None:
35 qs = self.model._default_manager.none()
36 else:
37 if queryset is None:
38 queryset = self.model._default_manager
39 qs = queryset.filter(
40 **{
41 self.ct_field.name: ContentType.objects.get_for_model(
42 self.instance, for_concrete_model=self.for_concrete_model
43 ),
44 self.ct_fk_field.name: self.instance.pk,
45 }
46 )
47 super().__init__(queryset=qs, data=data, files=files, prefix=prefix, **kwargs)
49 def initial_form_count(self):
50 if self.save_as_new:
51 return 0
52 return super().initial_form_count()
54 @classmethod
55 def get_default_prefix(cls):
56 opts = cls.model._meta
57 return (
58 opts.app_label
59 + "-"
60 + opts.model_name
61 + "-"
62 + cls.ct_field.name
63 + "-"
64 + cls.ct_fk_field.name
65 )
67 def save_new(self, form, commit=True):
68 setattr(
69 form.instance,
70 self.ct_field.get_attname(),
71 ContentType.objects.get_for_model(self.instance).pk,
72 )
73 setattr(form.instance, self.ct_fk_field.get_attname(), self.instance.pk)
74 return form.save(commit=commit)
77def generic_inlineformset_factory(
78 model,
79 form=ModelForm,
80 formset=BaseGenericInlineFormSet,
81 ct_field="content_type",
82 fk_field="object_id",
83 fields=None,
84 exclude=None,
85 extra=3,
86 can_order=False,
87 can_delete=True,
88 max_num=None,
89 formfield_callback=None,
90 validate_max=False,
91 for_concrete_model=True,
92 min_num=None,
93 validate_min=False,
94 absolute_max=None,
95 can_delete_extra=True,
96):
97 """
98 Return a ``GenericInlineFormSet`` for the given kwargs.
100 You must provide ``ct_field`` and ``fk_field`` if they are different from
101 the defaults ``content_type`` and ``object_id`` respectively.
102 """
103 opts = model._meta
104 # if there is no field called `ct_field` let the exception propagate
105 ct_field = opts.get_field(ct_field)
106 if (
107 not isinstance(ct_field, models.ForeignKey)
108 or ct_field.remote_field.model != ContentType
109 ):
110 raise Exception("fk_name '%s' is not a ForeignKey to ContentType" % ct_field)
111 fk_field = opts.get_field(fk_field) # let the exception propagate
112 exclude = [*(exclude or []), ct_field.name, fk_field.name]
113 FormSet = modelformset_factory(
114 model,
115 form=form,
116 formfield_callback=formfield_callback,
117 formset=formset,
118 extra=extra,
119 can_delete=can_delete,
120 can_order=can_order,
121 fields=fields,
122 exclude=exclude,
123 max_num=max_num,
124 validate_max=validate_max,
125 min_num=min_num,
126 validate_min=validate_min,
127 absolute_max=absolute_max,
128 can_delete_extra=can_delete_extra,
129 )
130 FormSet.ct_field = ct_field
131 FormSet.ct_fk_field = fk_field
132 FormSet.for_concrete_model = for_concrete_model
133 return FormSet