1

Attempting to use bootstrap4 with django for forms. Installed crispy forms and and everything seems to work as I expected except for the browse file button selection functionality. When a file selection window comes up and file is choosen from explorer it does not show as selected it the field. However when the form is submitted everything works as expected and the file is uploaded. Am I missing a helper class setting? I could not find one that looked like it addresses this.

Any help is appreciated, details below.

rendered html

Environment:

  • Windows 10
  • bootstrap 4.3.1
  • Python 3.7.4
  • Django 2.2.5
  • Django crispy forms 1.8.0

Models.py

    from django.db import models

    # Create your models here.

    class Csvfile_model(models.Model):
        name = models.CharField(max_length=50)
        csv_file_name = models.FileField(upload_to='csv_file/')

forms.py

    from django import forms
    from crispy_forms.helper import FormHelper
    from .models import *

    class CsvForm(forms.ModelForm):
         helper = FormHelper()

         class Meta:
              model = Csvfile_model
              fields = ['name', 'csv_file_name']

views.py

    from django.shortcuts import render,redirect
    from django.http import HttpResponse
    from .forms import *
    # Create your views here.
    def csv_upload(request):
        if request.method == "POST":
            form = CsvForm(request.POST, request.FILES)
            if form.is_valid():
                form.save()
                return redirect('sucess')
        else:
            form = CsvForm()
        return render(request, 'csv_upload.html', {'form' : form})

    def sucess(request):
        return HttpResponse('sucessfully uploaded')

csv_upload.html

<!-- templates/home.html -->
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% crispy form form.helper %}

{% block title %}Home{% endblock %}

{%block subject%} <h1>Pandas Profiler Home</h1> {% endblock %}

{% block content %}
<div class="container">
        <div class="row">
                <div class="col-12">
                        <h2> CSV Upload</h2>
                        <div class="row">
                                <form method = "post" enctype="multipart/form-data">
                                    {% csrf_token %}
                                    <div class="input-group">
                                         {% crispy form %}
                                         <span class="input-group-btn">
                                             <button class="btn btn-default" type="submit"> Upload </button>
                                         </span>
                                     </div>
                                 </form>
                        </div>
                </div class="col-12">
        </div class="row">
</div class="container">
{% endblock %}

base.html

<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <title>{% block title %}Django Auth Tutorial{% endblock %}</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
  <style>
  .fakeimg {
    height: 200px;
    background: #aaa;
  }
  </style>
</head>
<body>

<div class="jumbotron text-center" style="margin-bottom:0">
  <subject>{% block subject %} <h1> Django Auth Tutorial </h1>{% endblock %}</subject>
  <p>Quick and dirt responsive website to do eploratory data analysis (EDA) </p>
</div>

<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
  <a class="navbar-brand" href="#">Menu</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="collapsibleNavbar">
    <ul class="navbar-nav">
      <li class="nav-item">
        <a class="nav-link" href="#">Home</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">About</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Contact Us</a>
      </li>
    </ul>
  </div>
</nav>

<div class="container" style="margin-top:30px">
  <div class="row">
    <div class="col-sm-12">
        {% block content %}
        {% endblock %}
    </div>
  </div>
</div>

<div class="jumbotron text-center" style="margin-bottom:0">
  <p>Pandas Profiler is an experiment using django, bootstrap to upload a file to a website, process that file and display the results back to the user withouth having to know python or pandas.  It's also great for lazy data scientests</p>
</div>

</body>
</html>

settings.py

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'y(9-(8p)v+s8!i#f0&4_@#zd#lw3qq9^fj@$e7vt(#&%7kih_o'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',                                                                                                                                                  'django.contrib.staticfiles',                                                                                                                                               'csvfile.apps.CsvfileConfig',
    'crispy_forms',
]

...


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
Brad Allgood
  • 29
  • 1
  • 5
  • Do you have javascript enabled? https://stackoverflow.com/questions/48613992/bootstrap-4-file-input-doesnt-show-the-file-name/51928387 – user2707389 Nov 20 '19 at 14:58
  • I've included my base.html to the post. I believe the following in the section satisfies this although I may be wrong. Thoughts? ' – Brad Allgood Nov 20 '19 at 15:08
  • I'm seeing a lot of references to custom fields and modified javascript I'm just not sure how this all works with the django and django-crispy-forms level abstraction. I'm continuing to research and educate myself on the custom fields, custom forms, there just seems to be sparse information available outside the django-crispy-forms documentation. Does anyone have additional resources or suggestions on resources to study? – Brad Allgood Nov 20 '19 at 16:09
  • So It has been a while since I had to make a form. But this has always been my starting point:. https://simpleisbetterthancomplex.com/tutorial/2018/11/28/advanced-form-rendering-with-django-crispy-forms.html – user2707389 Nov 21 '19 at 00:13

1 Answers1

1

This is bootstrap4 functionality and not crispy. To correct this you need to add some javascript to interact with the form button and the filename field. Insert this at the bottom of your html file and it should work.

<script type="application/javascript">
    $('input[type="file"]').change(function(e){
        var fileName = e.target.files[0].name;
        $('.custom-file-label').html(fileName);
    });
</script>