У меня проблемы с crispy_forms и наборами форм
Я использую django_crispy_forms и имею 2 набора форм внутри главной формы. Формсеты генерируют & сохраняют данные правильно, за исключением первой строки, данные в которой никогда не сохраняются. В источнике страницы первая строка не имеет номера экземпляра, а вторая строка имеет номер экземпляра 0. Например, id vegetationType для первой строки - id_vegetation-prefix-VegetationType, для второй строки - id_vegetation-0-VegetationType. Если я удалю помощник формы из html страницы ({% crispy formset_vegetation%} вместо {% crispy formset_vegetation formset_vegetation.form.helper%}, то набор форм отображается правильно без лишней строки сверху, но строки не форматируются как инлайн набор форм.
Кто-нибудь видит, что я делаю неправильно?
models.py
class Landcover(models.Model):
Site = models.ForeignKey(Site, on_delete=models.RESTRICT, default=None, blank=True, editable=True, verbose_name='1. Site Name')
Recorders = models.ManyToManyField(ProjectStaff, default=None, verbose_name = '2. Recorders(s)', help_text='select all that apply')
Date = models.DateField(default=None, verbose_name='3. Date')
Latitude = models.DecimalField(max_digits=9, decimal_places=6, default=None, verbose_name='4. Latitude')
Longitude = models.DecimalField(max_digits=9, decimal_places=6, default=None, verbose_name='5. Longitude')
class VegetationLevels(models.Model):
Landcover = models.ForeignKey(Landcover, on_delete=models.RESTRICT, default=None, editable=True)
VegetationLevel = models.ForeignKey(VegetationLevel, on_delete=models.RESTRICT, default=None, verbose_name='Vegetation Level')
VegetationType = models.ManyToManyField(VegetationType, default=None, verbose_name='Vegetation Types')
class DensiometerReadings(models.Model):
Landcover = models.ForeignKey(Landcover, on_delete=models.RESTRICT, default=None, editable=True)
Latitude = models.DecimalField(max_digits=9, decimal_places=6, default=None)
Longitude = models.DecimalField(max_digits=9, decimal_places=6, default=None)
Reading = models.IntegerField(default=None, blank=True, verbose_name='Open Canopy Reading')
forms.py
class LandcoverForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
super(LandcoverForm, self).__init__(*args, **kwargs)
self.fields['Date'].widget = forms.DateInput(attrs={'type':'date'})
class Meta:
model = Landcover
fields = '__all__'
widgets = {
'Recorders': forms.CheckboxSelectMultiple
}
class VegetationLevelsForm(ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.template = 'bootstrap/table_inline_formset.html'
super(VegetationLevelsForm, self).__init__(*args, **kwargs)
class Meta:
model = VegetationLevels
fields = ('VegetationLevel','VegetationType','Percentage','Photo')
class DensiometerReadingsForm(ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.template = 'bootstrap/table_inline_formset.html'
super(DensiometerReadingsForm, self).__init__(*args, **kwargs)
class Meta:
model = DensiometerReadings
fields = ('Latitude','Longitude','Reading',)
views.py
def landcover_edit(request, landcover_id):
land = get_object_or_404(Landcover, id=landcover_id)
VegetationFormset = inlineformset_factory(Landcover, VegetationLevels, form=VegetationLevelsForm, extra=2, max_num=3, can_delete=False)
DensioFormset = inlineformset_factory(Landcover, DensiometerReadings, form=DensiometerReadingsForm, extra=0, max_num=20, can_delete=True)
if request.method == "POST":
form = LandcoverForm(request.POST, instance=land)
formset_vegetation = VegetationFormset(request.POST, request.FILES, prefix='vegetation', instance=land)
formset_densio = DensioFormset(request.POST, request.FILES, prefix='densio', instance=land)
if form.is_valid() and formset_densio.is_valid() and formset_vegetation.is_valid():
new_landcover = form.save(commit=True)
formset_vegetation.save(commit=True)
formset_densio.save(commit=True)
return redirect('landcover_list')
else:
form = LandcoverForm(instance=land)
form.fields['Site'].disabled = True
formset_vegetation = VegetationFormset(instance=land, prefix='vegetation')
formset_densio = DensioFormset(instance=land, prefix='densio')
return render(request, "eeidi/landcover_edit.html", {"form":form, "formset_densio": formset_densio, "formset_vegetation": formset_vegetation, 'title': 'Edit'})
landcover_edit.html
...
<div class="form-inline">
<h8>Vegetation Types</h8>
{% crispy formset_vegetation formset_vegetation.form.helper%}
</div>
...