Comment est-ce que je dénomme ce qui suit:
dans forms.py -
from Django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
dans contact_form.html -
<form action="" method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
Par exemple, comment définir une classe ou un ID pour le sujet, l'e-mail ou le message auquel fournir une feuille de style externe? Je vous remercie
Tiré de ma réponse à: Comment baliser des champs de formulaire avec <div class = 'field_type'> dans Django
class MyForm(forms.Form):
myfield = forms.CharField(widget=forms.TextInput(attrs={'class' : 'myfieldclass'}))
ou
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['myfield'].widget.attrs.update({'class' : 'myfieldclass'})
ou
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),
}
--- MODIFIER ---
La modification ci-dessus est la modification la plus facile à apporter au code de la question d'origine qui accomplit ce qui a été demandé. Cela vous empêche également de vous répéter si vous réutilisez le formulaire ailleurs; vos classes ou autres attributs ne fonctionnent que si vous utilisez les méthodes de formulaire as_table/as_ul/as_p de Django. Si vous avez besoin d’un contrôle total pour un rendu entièrement personnalisé, c’est clairement documenté
- EDIT 2 ---
Ajout d'une méthode plus récente pour spécifier un widget et des attributs pour un ModelForm.
Cela peut être fait en utilisant un filtre de modèle personnalisé . Considérant que vous rendez le formulaire de cette façon:
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
<span class="helptext">{{ form.subject.help_text }}</span>
</div>
</form>
form.subject est une instance de BoundField qui a la méthode as_widget.
vous pouvez créer un filtre personnalisé "addclass" dans "my_app/templatetags/myfilters.py"
from Django import template
register = template.Library()
@register.filter(name='addclass')
def addclass(value, arg):
return value.as_widget(attrs={'class': arg})
Et ensuite appliquez votre filtre:
{% load myfilters %}
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject|addclass:'MyClass' }}
<span class="helptext">{{ form.subject.help_text }}</span>
</div>
</form>
form.subjects sera ensuite rendu avec la classe css "MyClass".
J'espère que cette aide.
Si vous ne souhaitez pas ajouter du code aucun au formulaire (comme indiqué dans les commentaires à la réponse de @ shadfc), il est certainement possible, voici deux options.
Tout d’abord, il vous suffit de référencer les champs individuellement dans le code HTML, plutôt que l’ensemble du formulaire à la fois:
<form action="" method="post">
<ul class="contactList">
<li id="subject" class="contact">{{ form.subject }}</li>
<li id="email" class="contact">{{ form.email }}</li>
<li id="message" class="contact">{{ form.message }}</li>
</ul>
<input type="submit" value="Submit">
</form>
(Notez que je l'ai également remplacé par un liste non classé.)
Deuxièmement, notez dans la documentation sur la sortie des formulaires au format HTML , Django:
L'identifiant de champ, est généré par en ajoutant 'id_' au nom du champ . Les attributs et balises id sont inclus dans la sortie par défaut.
Tous vos champs de formulaire ont déjà un unique id. Vous feriez donc référence à id_subject dans votre fichier CSS pour styliser le champ sujet. Je dois noter que voici comment le formulaire se comporte lorsque vous prenez le par défaut HTML, qui nécessite simplement d’imprimer le formulaire, pas les champs individuels:
<ul class="contactList">
{{ form }} # Will auto-generate HTML with id_subject, id_email, email_message
{{ form.as_ul }} # might also work, haven't tested
</ul>
Voir le lien précédent pour d'autres options lors de la sortie de formulaires (vous pouvez créer des tableaux, etc.).
Remarque - Je réalise que ce n'est pas la même chose que d'ajouter un classe à chaque élément (si vous ajoutez un champ au formulaire, vous devrez également mettre à jour le CSS) - mais il est assez facile de le référencer tous les champs par id dans votre CSS comme ceci:
#id_subject, #id_email, #email_message
{color: red;}
Vous pouvez faire comme ça:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
subject.widget.attrs.update({'id' : 'your_id'})
J'espère que ça marche.
Ignas
Per this blog, vous pouvez ajouter des classes CSS à vos champs en utilisant un filtre de modèle personnalisé.
from Django import template
register = template.Library()
@register.filter(name='addcss')
def addcss(field, css):
return field.as_widget(attrs={"class":css})
Mettez ceci dans le dossier templatetags/de votre application et vous pouvez maintenant faire
{{field|addcss:"form-control"}}
Vous pouvez utiliser cette bibliothèque: https://pypi.python.org/pypi/Django-widget-tweaks
Cela vous permet de faire ce qui suit:
{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}
Tu peux faire:
<form action="" method="post">
<table>
{% for field in form %}
<tr><td>{{field}}</td></tr>
{% endfor %}
</table>
<input type="submit" value="Submit">
</form>
Ensuite, vous pouvez ajouter des classes/id à par exemple la balise <td>
. Vous pouvez bien sûr utiliser les autres balises de votre choix. Vérifiez Utilisation des formulaires Django , à titre d’exemple, de ce qui est disponible pour chaque field
du formulaire ({{field}}
, par exemple, n’affiche que la balise d’entrée, pas l’étiquette, etc.).
Vous n'avez peut-être pas besoin de remplacer le __init__
de votre classe de formulaire, car Django définit les attributs name
& id
dans HTML input
s. Vous pouvez avoir CSS comme ça:
form input[name='subject'] {
font-size: xx-large;
}
Je n'ai pas vu celui-ci vraiment ...
https://docs.djangoproject.com/fr/1.8/ref/forms/api/#more-granular-output
Les méthodes as_p (), as_ul () et as_table () ne sont que des raccourcis pour les développeurs paresseux - ce n’est pas le seul moyen d’afficher un objet de formulaire.
class BoundField Utilisé pour afficher le HTML ou les attributs d'accès pour un seul champ d'une instance de formulaire.
La méthode str () (unicode sous Python 2) de cet objet affiche le code HTML de ce champ.
Pour récupérer un seul BoundField, utilisez la syntaxe de recherche par dictionnaire sur votre formulaire en utilisant le nom du champ comme clé:
>>> form = ContactForm()
>>> print(form['subject'])
<input id="id_subject" type="text" name="subject" maxlength="100" />
Pour récupérer tous les objets BoundField, itérez le formulaire:
>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
<input id="id_subject" type="text" name="subject" maxlength="100" />
<input type="text" name="message" id="id_message" />
<input type="email" name="sender" id="id_sender" />
<input type="checkbox" name="cc_myself" id="id_cc_myself" />
La sortie spécifique au champ respecte le paramètre auto_id de l’objet formulaire:
>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
<input type="text" name="message" />
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
<input type="text" name="message" id="id_message" />
Il existe un outil très facile à installer et très utile pour Django que je utilise pour le style et qui peut être utilisé pour tous les environnements frontaux tels que Bootstrap, Materialise, Foundation, etc. Il s’appelle widget-tweaks Documentation: Widget Tweaks
depuis les formulaires d'importation Django
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
Au lieu d'utiliser default:
{{ form.as_p }} or {{ form.as_ul }}
Vous pouvez l'éditer à votre façon en utilisant l'attribut render_field qui vous donne un moyen de le styler plus proche du HTML, comme dans cet exemple:
template.html
{% load widget_tweaks %}
<div class="container">
<div class="col-md-4">
{% render_field form.subject class+="form-control myCSSclass" placeholder="Enter your subject here" %}
</div>
<div class="col-md-4">
{% render_field form.email type="email" class+="myCSSclassX myCSSclass2" %}
</div>
<div class="col-md-4">
{% render_field form.message class+="myCSSclass" rows="4" cols="6" placeholder=form.message.label %}
</div>
</div>
Cette bibliothèque vous donne l’opportunité d’avoir votre front end bien séparé de votre backend
Dans Django 1.10 (éventuellement plus tôt également), vous pouvez le faire comme suit.
Modèle:
class Todo(models.Model):
todo_name = models.CharField(max_length=200)
todo_description = models.CharField(max_length=200, default="")
todo_created = models.DateTimeField('date created')
todo_completed = models.BooleanField(default=False)
def __str__(self):
return self.todo_name
Forme:
class TodoUpdateForm(forms.ModelForm):
class Meta:
model = Todo
exclude = ('todo_created','todo_completed')
Modèle:
<form action="" method="post">{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.todo_name.errors }}
<label for="{{ form.name.id_for_label }}">Name:</label>
{{ form.todo_name }}
</div>
<div class="fieldWrapper">
{{ form.todo_description.errors }}
<label for="{{ form.todo_description.id_for_label }}">Description</label>
{{ form.todo_description }}
</div>
<input type="submit" value="Update" />
</form>
Une solution consiste à utiliser JavaScript pour ajouter les classes CSS requises une fois la page prête. Par exemple, pour styliser la sortie de formulaire Django avec des classes d’amorçage (jQuery utilisé pour abréger):
<script type="text/javascript">
$(document).ready(function() {
$('#some_Django_form_id').find("input[type='text'], select, textarea").each(function(index, element) {
$(element).addClass("form-control");
});
});
</script>
Cela évite la laideur de mélanger les spécificités de style avec la logique de votre entreprise.
Écrivez votre formulaire comme:
class MyForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attr={'class':'name'}))
message = forms.CharField(widget=forms.Textarea(attr={'class':'message'}))
Dans votre champ HTML, faites quelque chose comme:
{% for field in form %}
<div class="row">
<label for="{{ field.name}}">{{ field.name }}</label>{{ field }}
</div>
{% endfor %}
Ensuite, dans votre CSS, écrivez quelque chose comme:
.name{
/* you already have this class so create it's style form here */
}
.message{
/* you already have this class so create it's style form here */
}
label[for='message']{
/* style for label */
}
J'espère que cette réponse vaut la peine d'essayer! Notez que vous devez avoir écrit vos vues pour rendre le fichier HTML contenant le formulaire.
Edit: Une autre façon (légèrement meilleure) de faire ce que je suggère est la réponse ici: Style de champ de saisie de formulaire Django
Toutes les options ci-dessus sont géniales, je pensais juste y ajouter celle-ci car elle est différente.
Si vous voulez un style personnalisé, des classes, etc. sur vos formulaires, vous pouvez effectuer une entrée html dans votre modèle qui correspond à votre champ de formulaire. Pour un CharField, par exemple, (le widget par défaut est TextInput
), supposons que vous souhaitiez une saisie de texte d’apparence amorce. Vous feriez quelque chose comme ça:
<input type="text" class="form-control" name="form_field_name_here">
Et tant que vous mettez le nom du champ de formulaire correspond à l'attribut html name
(et que le widget doit probablement correspondre également au type d'entrée), Django exécutera tous les mêmes validateurs sur ce champ lorsque vous exécuterez validate
ou form.is_valid()
et
Styliser d'autres éléments tels que les étiquettes, les messages d'erreur et le texte d'aide ne nécessite pas beaucoup de solutions de contournement, car vous pouvez utiliser quelque chose comme form.field.error.as_text
et les styler comme vous le souhaitez. Les champs réels sont ceux qui nécessitent un peu de bidouillage.
Je ne sais pas si c'est la meilleure façon, ou celle que je recommanderais, mais c'est une façon, et cela pourrait convenir à quelqu'un.
Voici un guide pratique des formulaires de style qui inclut la plupart des réponses répertoriées dans SO (comme l'utilisation de attr sur les widgets et les modifications de widget) . https://simpleisbetterthancomplex.com/article/2017 /08/19/how-to-render-Django-form-manually.html
Styling des instances de widgets
Si vous souhaitez rendre une instance de widget différente d'une autre, vous devez spécifier des attributs supplémentaires au moment où l'objet de widget est instancié et affecté à un champ de formulaire (et peut-être ajouter des règles à vos fichiers CSS).
https://docs.djangoproject.com/fr/2.2/ref/forms/widgets/
Pour ce faire, vous utilisez l'argument Widget.attrs lors de la création du widget:
class CommentForm(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
url = forms.URLField()
comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))
Vous pouvez également modifier un widget dans la définition de formulaire:
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField()
name.widget.attrs.update({'class': 'special'})
comment.widget.attrs.update(size='40')
Ou si le champ n'est pas déclaré directement sur le formulaire (tel que les champs du formulaire modèle), vous pouvez utiliser l'attribut Form.fields:
class CommentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'class': 'special'})
self.fields['comment'].widget.attrs.update(size='40')
Django inclura ensuite les attributs supplémentaires dans la sortie rendue:
>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" class="special" required></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40" required></td></tr>