je crée une vue qui retourne une forme comprenant un formulaire de contact et deux formes de phone_number, suivant cet exemple:django édition en ligne - formulaire en ligne uniquement nécessaire si au moins un champ est rempli
Le le numéro de téléphone formes ne doivent être validés si l'utilisateur insère au moins une valeur pour un champ dans une forme de numéro de téléphone. Par exemple: un numéro de téléphone a un type et un numéro. Si l'utilisateur sélectionne le type, le numéro est requis.
Maintenant, je me demande comment je peux vérifier dans la vue si l'utilisateur a inséré une valeur/sélectionné un type ou inséré un numéro. Cela devrait fonctionner comme dans l'admin pour l'édition en ligne d'un modèle.
mon avis ressemble à ceci:
def contact_add(request):
user = request.user
if request.method == 'POST':
cform = ContactForm(request.POST)
pforms = [PhoneNumberForm(request.POST, prefix=str(x)) for x in range(0,3)]
if cform.is_valid() and all([pf.is_valid() for pf in pforms]):
new_contact = cform.save(commit=False)
new_contact.created_by = user
new_contact.save()
for pf in pforms:
new_phone_number = pf.save(commit=False)
new_phone_number.contact = new_contact
new_phone_number.save()
request.user.message_set.create(message='Contact %s has been added.' % new_contact.__str__())
return HttpResponseRedirect("/crm/contacts/?oby=1")
else:
cform = ContactForm()
pforms = [PhoneNumberForm(prefix=str(x)) for x in range(0,3)]
return render_to_response(
'crm/contact_add.html',
{'cform': cform, 'pforms': pforms,},
context_instance = RequestContext(request),
)
Modifier après la première réponse ci-dessous:
J'ai essayé d'accomplir cette tâche avec validation personnalisée, mais ne sont pas venus à une fin satisfaisante. Pour faciliter ma tâche, j'ai changé un peu le cas d'utilisation. Je crée un formulaire qui comprend un formulaire de contact et un formulaire d'adresse. Le formulaire d'adresse doit être validée si au moins un champ du formulaire d'adresse est rempli, car il devrait être possible de créer un contact sans créer une adresse correspondante.
Tout d'abord j'ai essayé d'utiliser la validation de custume, qui ressemblait à ceci:
class AddressForm(forms.ModelForm):
class Meta:
model = Address
exclude = ('contact',)
def clean(self):
cleaned_data = self.cleaned_data
street = cleaned_data.get("street")
postal_code = cleaned_data.get("postal_code")
city = cleaned_data.get("city")
country = cleaned_data.get("country")
if not street and not postal_code and not city and not country:
#searching a better idea here
return 0
else:
return cleaned_data
Mais cela ne fonctionne pas vraiment, puisque de cette façon que je ne vous débarrassez pas des erreurs de validation. Cela m'amène à l'idée que la méthode propre est le mauvais endroit pour faire cette validation, je pense que je dois vérifier dans la demande POST si toutes les valeurs pour le formulaire d'adresse sont manquantes. Et s'ils sont manquants, je n'appelle pas is_valid() pour le formulaire d'adresse et je l'ignore. Si au moins une valeur est disponible, je fais juste la validation normale du formulaire d'adresse, sans surcharger la méthode clean().
Bonne ou mauvaise idée? Si elle est une bonne idée, comment puis-je vérifier facilement la requête POST pour les valeurs de mon formulaire d'adresse.
façon de penser probablement à I`m compliqué :-)
Edit: La solution à l'aide Formsets:
@login_required
def contact_add(request):
user = request.user
if request.method == 'POST':
cform = ContactForm(request.POST)
phonenumberformset = PhoneNumberFormSet(request.POST)
if cform.is_valid() and classificationformset.is_valid() and addressformset.is_valid() and phonenumberformset.is_valid():
new_contact = cform.save(commit=False)
new_contact.created_by = user
new_contact.save()
new_phonenumber_instances = phonenumberformset.save(commit=False)
for new_phonenumber in new_phonenumber_instances:
new_phonenumber.contact = new_contact
new_phonenumber.save()
request.user.message_set.create(message='Contact %s has been added.' % new_contact.__str__())
return HttpResponseRedirect("/crm/contacts/?oby=1")
else:
cform = ContactForm()
#By default, when you create a formset from a model, the formset will use
#a queryset that includes all objects in the model (e.g., Author.objects.all()).
#Here we want to present an empty formset in order to add a new object
phonenumberformset = PhoneNumberFormSet(queryset=PhoneNumber.objects.none())
return render_to_response(
'crm/contact_add.html',
{'cform': cform, 'phonenumberformset': phonenumberformset,},
context_instance = RequestContext(request),
)
S'il vous plaît noter que cela peut aussi être réalisé en utilisant un inlineformset_factory, voir mon autre poste pour plus de détails: link
Notez que si vous utilisez formsets vous devez inclure un management_form pour chaque form_set dans votre modèle. docs
Sinon, vous obtenez cette erreur:
[u'ManagementForm data is missing or has been tampered with']
Using a formset inside a view is as easy as using a regular Form class. The only thing you will want to be aware of is making sure to use the management form inside the template.
{{ context.phonenumberformset.management_form }}
Formulaires? Je n'en ai jamais entendu parler. Je vais essayer. Ça sonne bien :-) –
Mais pour mon cas d'utilisation ci-dessus, si je crée un Formset pour un formulaire d'adresse. Est-ce que le formset vérifie que l'utilisateur n'a pas rempli de données et ne le valide pas? –
Ok ça marche. Va l'essayer aussi pour les autres inlines et poster le résultat dans ma question! –