J'essaie d'adapter une approche pour enregistrer des ensembles de formulaires imbriqués avec le formulaire principal à l'aide de la fonctionnalité de mise en page Django-Crispy-Forms, mais je ne peux pas l'enregistrer. Je suis en train de suivre cet exemple de projet, mais je n'ai pas pu valider formset pour enregistrer les données. Je serai vraiment reconnaissant si quelqu'un peut signaler mon erreur. J'ai également besoin d'ajouter trois inlines dans la même vue pour EmployeeForm. J'ai essayé Django-Extra-Views mais je n'ai pas pu faire fonctionner ça. J'apprécierais si vous conseillez d'ajouter plus d'une ligne pour la même vue, comme environ 5. Tout ce que je veux, c'est une seule page pour la création Employee
et ses lignes comme Education, Experience, Others
. Voici le code:
des modèles:
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employees',
null=True, blank=True)
about = models.TextField()
street = models.CharField(max_length=200)
city = models.CharField(max_length=200)
country = models.CharField(max_length=200)
cell_phone = models.PositiveIntegerField()
landline = models.PositiveIntegerField()
def __str__(self):
return '{} {}'.format(self.id, self.user)
def get_absolute_url(self):
return reverse('bars:create', kwargs={'pk':self.pk})
class Education(models.Model):
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, related_name='education')
course_title = models.CharField(max_length=100, null=True, blank=True)
institute_name = models.CharField(max_length=200, null=True, blank=True)
start_year = models.DateTimeField(null=True, blank=True)
end_year = models.DateTimeField(null=True, blank=True)
def __str__(self):
return '{} {}'.format(self.employee, self.course_title)
Vue:
class EmployeeCreateView(CreateView):
model = Employee
template_name = 'bars/crt.html'
form_class = EmployeeForm
success_url = None
def get_context_data(self, **kwargs):
data = super(EmployeeCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['education'] = EducationFormset(self.request.POST)
else:
data['education'] = EducationFormset()
print('This is context data {}'.format(data))
return data
def form_valid(self, form):
context = self.get_context_data()
education = context['education']
print('This is Education {}'.format(education))
with transaction.atomic():
form.instance.employee.user = self.request.user
self.object = form.save()
if education.is_valid():
education.save(commit=False)
education.instance = self.object
education.save()
return super(EmployeeCreateView, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('bars:detail', kwargs={'pk':self.object.pk})
Formes:
class EducationForm(forms.ModelForm):
class Meta:
model = Education
exclude = ()
EducationFormset =inlineformset_factory(
Employee, Education, form=EducationForm,
fields=['course_title', 'institute_name'], extra=1,can_delete=True
)
class EmployeeForm(forms.ModelForm):
class Meta:
model = Employee
exclude = ('user', 'role')
def __init__(self, *args, **kwargs):
super(EmployeeForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = True
self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-md-3 create-label'
self.helper.field_class = 'col-md-9'
self.helper.layout = Layout(
Div(
Field('about'),
Field('street'),
Field('city'),
Field('cell_phone'),
Field('landline'),
Fieldset('Add Education',
Formset('education')),
HTML("<br>"),
ButtonHolder(Submit('submit', 'save')),
)
)
Objet de mise en page personnalisé selon l'exemple:
from crispy_forms.layout import LayoutObject, TEMPLATE_PACK
from django.shortcuts import render
from django.template.loader import render_to_string
class Formset(LayoutObject):
template = "bars/formset.html"
def __init__(self, formset_name_in_context, template=None):
self.formset_name_in_context = formset_name_in_context
self.fields = []
if template:
self.template = template
def render(self, form, form_style, context, template_pack=TEMPLATE_PACK):
formset = context[self.formset_name_in_context]
return render_to_string(self.template, {'formset': formset})
Formset.html:
{% load static %}
{% load crispy_forms_tags %}
{% load staticfiles %}
<table>
{{ formset.management_form|crispy }}
{% for form in formset.forms %}
<tr class="{% cycle 'row1' 'row2' %} formset_row-{{ formset.prefix }}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field|as_crispy_field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<br>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
</script>
<script src="{% static 'js/jquery.formset.js' %}">
</script>
<script type="text/javascript">
$('.formset_row-{{ formset.prefix }}').formset({
addText: 'add another',
deleteText: 'remove',
prefix: '{{ formset.prefix }}',
});
</script>
Il n'y a aucune erreur dans le terminal et / ou autrement. L'aide est très appréciée.