forms.FileField mit bootstrap 4 formatieren

Django, Flask, Bottle, WSGI, CGI…
Antworten
k.marco.1970
User
Beiträge: 48
Registriert: Mittwoch 25. Dezember 2013, 20:46

Hallo Forum,

ich nutze eine django Form zum Upload von Dateien. Zum Formatieren der Seite verwende ich bootstrap 4. Nun bin ich auf der Suche nach einer Möglichkeit, um den Upload Button mit bootstrap 4 zu gestalten und da würde ich mich über Hilfe freuen. Denn bisher wird dieser Button nur als "normaler" Button ausgegeben, also ohne jegliches schickes Design, das bootstrap bietet.

Meine Codes sehen vom Prinzip her - ohne alles reinzukopieren - so aus:

forms.py

Code: Alles auswählen

from django import forms
class DocumentForm(forms.Form):
    docfile = forms.FileField(label='Laden Sie Ihre Datei hoch')
    CHOICES=[('auswahl','Beschriftung'),]
    modus = forms.ChoiceField(choices=CHOICES, widget=forms.RadioSelect())
    
views.py

Code: Alles auswählen

def dateiupload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            try:
                newdoc = Document(docfile = request.FILES['docfile'], modus = request.POST['modus'])
                auswahl = request.POST['modus']
                statInstance = str(newdoc.docfile)
            except:
                if request.LANGUAGE_CODE == "de":
                    return render(request,
                                folder_of_app+'/FehlermeldungDE.html',
                                )
                else:
                    return render(request,
                                folder_of_app+'/FehlermeldungEN.html',
                                )
            newdoc.save()

ausgabe.html

Code: Alles auswählen

           <h2><span class="label label-default">Upload</span></h2><br><br>
					<form action="{% url "dateiupload" %}" method="post" enctype="multipart/form-data">
						{% csrf_token %}
						<p>{{ form.non_field_errors }}</p>
						<p><b>1. {{ form.docfile.label_tag }} {{ form.docfile.help_text }}</b></p>
						<p>
						    {{ form.docfile.errors }}
						    {{ form.docfile }}
						</p>
						<br>
						    <b>Wählen Sie</b>
						    <br>
						    <br>
							<div class="">
							  <div class="col-lg-1">
								<div class="input-group">
								  <span class="input-group-addon">
									<input type="radio" name="modus" value="driving"> Meine Wahl</span>
								</div><!-- /input-group -->
							  </div><!-- /.col-lg-1 -->
							</div>  
							<br>
							<br><b>Lade hoch </b>
							<br>
							<div class="btn-group" role="group" aria-label="...">
							  <button type="submit" class="btn btn-default">Los gehts!</button>
							</div>
				    </form>
Das was ich unter ausgabe.html nun habe, ist ein Teil, der ohne jegliches boostrap ausgegeben wird - was nicht so schön ist.

Code: Alles auswählen

						<p>{{ form.non_field_errors }}</p>
						<p><b>1. {{ form.docfile.label_tag }} {{ form.docfile.help_text }}</b></p>
						<p>
						    {{ form.docfile.errors }}
						    {{ form.docfile }}
						</p>
Kann hier jemand helfen? Könnte ich z. B. mit crispy-Forms etwas erreichen?

Viele Grüße
Marco
Benutzeravatar
noisefloor
User
Beiträge: 4250
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ich bin jetzt nicht wirklich sicher, ob ich dein tatsächliches Problem verstehe... du musst dem Button doch im Template nur die CSS-Klassen deiner Wahl verpassen. Wie halt in "jeder " HTML-Datei. Das hat mir Django nichts zu tun.

Und natürlich nicht vergessen, dass CSS-Framework einzubinden.

Gruß, noisefloor
k.marco.1970
User
Beiträge: 48
Registriert: Mittwoch 25. Dezember 2013, 20:46

Hallo noisefloor,

ich bräuchte ja soetwas, damit es funktioniert (das ist jetzt ein Beispiel von der bootstrap-Seite):

Code: Alles auswählen

<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text">Upload</span>
  </div>
  <div class="custom-file">
    <input type="file" class="custom-file-input" id="inputGroupFile01">
    <label class="custom-file-label" for="inputGroupFile01">Choose file</label>
  </div>
</div>
An der Stelle weiß ich aber nicht, wie ich die einzelnen Elemente aus:

Code: Alles auswählen

						<p>{{ form.non_field_errors }}</p>
						<p><b>1. {{ form.docfile.label_tag }} {{ form.docfile.help_text }}</b></p>
						<p>
						    {{ form.docfile.errors }}
						    {{ form.docfile }}
						</p>
so zerlegen kann, dass es zu dem Boostrap-Beispiel passt, denn: das was im Input-Tag steht, wird ja von django über form.docfile geschrieben. Und darauf würde ich gerne Einfluss nehmen.
Im Moment gibt es den Button nämlich nur ohne bootstrap-Formatierung. Im restlichen Dokument funktioniert es, CSS ist eingebunden.

Viele Grüße
Marco
Benutzeravatar
noisefloor
User
Beiträge: 4250
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

ok. Die Form-Widges kennen das Argument `attrs` (Link), damit kann man dem Feld HTML-Attribute (wie `class="...") mitgeben. Beispiel für Bootstrap 4: https://simpleit.rocks/python/django/fo ... ngo-forms/.

Gruß, noisefloor
k.marco.1970
User
Beiträge: 48
Registriert: Mittwoch 25. Dezember 2013, 20:46

Hallo noisefloor,

danke für den Tip. Ich habe mich mal daran gemacht, das zu versuchen. Das Ergebnis, das ich inzwischen erreiche ist: ich bekommen das bootstrap-feld, ich kann eine Datei zum Hochladen auswählen, aber: wenn ich dann den Button in der Form drücke, um die Datei zu verarbeiten, gibt

Code: Alles auswählen

{{ form.docfile.errors }}
mir aus: "Dieses Feld ist zwingend", also die Datei ist doch nicht hochgeladen. In der Version ohne bootstrap steht an dieser Stelle immer der Name der Datei, die ich hochgeladen habe.

Meine Code-Teile sehen jetzt so aus:

forms.py

Code: Alles auswählen

class DocumentForm(forms.Form):
    docfile = forms.FileField(label='Laden Sie Ihre Datei hoch',
                              help_text="blabla",
                              widget=forms.TextInput(attrs={'class': 'custom-file-input',
                                                            "for": "inputGroupFile01",
                                                            "type": "file"
                                                            },
                                                     )
                              ) 
    print("docfile")
    print(docfile.label)
    print(docfile.help_text)
    print(docfile.widget.attrs)

Code: Alles auswählen

					<form action="{% url "meineView" %}" method="post" enctype="multipart/form-data">
						{% csrf_token %}
						{{ form.non_field_errors }}
<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text">Upload</span>
  </div>
  <div class="custom-file">
    
  <label class="custom-file-label" for="id_docfile" >{{ form.docfile.help_text }}</label>
  

  {{ form.docfile.errors }}{{ form.docfile }}

    
  </div>
</div>		
				
							<br><b>Starte Verarbeitung </b>
							<br>
							<div class="btn-group" role="group" aria-label="...">
							  <button type="submit" class="btn btn-default">Los gehts!</button>
							</div>
				    </form>

Und die Ausgabe im Anschluss im HTML-Code:

Code: Alles auswählen

				<form action="/meineView" method="post" enctype="multipart/form-data">
						<input type="hidden" name="csrfmiddlewaretoken" value="t5dgOCgmtbNWrf8HJ70uIyVXfYKigngX6WTRidtD9yzSAH1GstntHzCjuuQ5BkPs">
						
<div class="input-group mb-3">
  <div class="input-group-prepend">
    <span class="input-group-text">Upload</span>
  </div>
  <div class="custom-file">
    
  <label class="custom-file-label" for="id_docfile" >blabla</label>
  

  <input type="file" name="docfile" class="custom-file-input" for="inputGroupFile01" required id="id_docfile">

    
  </div>
</div>		
				
							<br><b>Starte Verarbeitung </b>
							<br>
							<div class="btn-group" role="group" aria-label="...">
							  <button type="submit" class="btn btn-default">Los gehts!</button>
							</div>
				    </form>

Würde jemand mir hierzu ein Feedback geben, wo der Fehler liegt?

Viele Grüße
Marco
Antworten