New experimental feature branch: subsections.

Despite the name, the idea is to allow reusable apps to add any kind of
formset to the edit page. The first test case is to allow madebyjane to
upload multiple images to a section.

Work in progress.
main
Jaap Joris Vens 2020-03-08 22:19:39 +01:00
rodzic 8bd8bdde47
commit da6cff19f6
3 zmienionych plików z 78 dodań i 3 usunięć

Wyświetl plik

@ -2,7 +2,6 @@ import swapper
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.mail import EmailMessage
from django.forms import inlineformset_factory
from django.utils.translation import gettext_lazy as _
Page = swapper.load_model('cms', 'Page')
@ -80,4 +79,62 @@ class SectionForm(forms.ModelForm):
# ignored entirely. Workaround to force a ChoiceField anyway:
type = forms.ChoiceField()
SectionFormSet = inlineformset_factory(Page, Section, form=SectionForm, extra=1)
#SectionFormSet = inlineformset_factory(Page, Section, form=SectionForm, extra=1)
def get_view(section):
if section:
return section.__class__.view_class()
class BaseSectionFormSet(forms.BaseInlineFormSet):
'''Potentially nested formset based on
https://www.yergler.net/2013/09/03/nested-formsets-redux/
If a Section subclass provides a 'formset_class' attribute, the
section form generated for the edit page will be given a 'formset'
attribute. This way, sections can customize their edit form to
request additional information.
Typical usecases could be:
- an images section that displays multiple images
- a column section that displays separate colums
- a calendar section that displays calendar events
- etc...
'''
def add_fields(self, form, index):
super().add_fields(form, index)
section = form.instance
view = get_view(section)
if hasattr(view, 'formset_class'):
form.formset = view.formset_class(
instance=section,
data=form.data if self.is_bound else None,
files=form.files if self.is_bound else None,
prefix=f'{form.prefix}-{view.formset_class.get_default_prefix()}')
#raise ValueError(form.formset)
def is_valid(self):
result = super().is_valid()
if self.is_bound:
for form in self.forms:
if hasattr(form, 'formset'):
result = result and form.formset.is_valid()
return result
def save(self, commit=True):
result = super().save(commit=commit)
for form in self:
if hasattr(form, 'formset'):
form.formset.save(commit=commit)
return result
SectionFormSet = forms.inlineformset_factory(
parent_model = Page,
model = Section,
form = SectionForm,
formset = BaseSectionFormSet,
extra=1,
)

Wyświetl plik

@ -53,6 +53,21 @@
{% endif %}
{% endfor %}
</div>
{{form.formset.management_form}}
{% for form in form.formset %}
<div class="anothersubform" style="padding: 10px; border:2px dotted black;margin-bottom: 10px">
{% for field in form.visible_fields %}
{% if field.name == 'DELETE' and not form.instance.pk %}
{% elif field.field.widget.input_type == 'checkbox' %}
{% include 'cms/formfield_checkbox.html' with field=field counter=forloop.parentloop.counter0 %}
{% else %}
{% include 'cms/formfield.html' with field=field counter=forloop.parentloop.counter0 %}
{% endif %}
{% endfor %}
</div>
{% endfor %}
</div>
</section>
</div>

Wyświetl plik

@ -62,6 +62,9 @@ class SectionFormSetView(SectionView):
kwargs['formset'] = self.get_formset()
return super().get_context_data(**kwargs)
def get_view(section):
return section.__class__.view_class()
class PageView(detail.DetailView):
'''View of a page with heterogeneous (polymorphic) sections'''
model = Page
@ -72,7 +75,7 @@ class PageView(detail.DetailView):
super().setup(*args, slug=slug, **kwargs)
def initialize_section(self, section):
section.view = section.__class__.view_class()
section.view = get_view(section)
section.view.setup(self.request, section)
section.context = section.view.get_context_data(
request = self.request,