yourlabs / django-autocomplete-light

A fresh approach to autocomplete implementations, specially for Django. Status: v4 alpha, v3 stable, v2 & v1 deprecated.
https://django-autocomplete-light.readthedocs.io
MIT License
1.81k stars 468 forks source link

DAL static files not added to static folder #1128

Open jothamgoh opened 4 years ago

jothamgoh commented 4 years ago

Hi All,

I've been trying to get DAL to work for a week or more, and I've read almost all the questions but can't seem to solve my problem.

I followed the tutorial, and after registering the autocomplete view, I'm able to open the view in a url (I can reverse the URL and see data).

However, I'm encountering the problem of not able to find the relevant JS files. They are not found in my static folder when I install DAL. This causes an empty dropdown as the pic below.

image

When I run python manage.py collectstatic, the auto-complete folder with some JS files appear in my static root but not my staticfile dir.

FYI my static file settings:

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]

I tried copying the autocomplete JS files from statfiles dir to static folder, and reference them in my template. However that did not work.

Am I missing something from the static folders? And which of the JS files should I add to my template? FYI im using a basic autocomplete.Select2QuerySetView outside the admin, and I ensured that {{ form.media }} tag is after the JS.

settings.py INSTALLED_APPS = [ 'dal', 'dal_select2', 'twotionapp.apps.TwotionappConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'phonenumber_field', 'formtools', 'crispy_forms', ]

base_form.py

{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Title -->
  <title>{% block title %}{% endblock title %}</title>

  <!-- CSS Implementing Plugins -->
  <link rel="stylesheet" href="{% static 'assets/vendor/font-awesome/css/fontawesome-all.min.css' %}">
  <link rel="stylesheet" media="all" href="{% static 'assets/autocomplete/select2.css' %}">

</head>

<body>
  <!-- ========== HEADER ========== -->
  <header>
  some stuff here
  </header>
  <!-- ========== END HEADER ========== -->

{% block content %}
{% endblock content %}

  <!-- ========== FOOTER ========== -->
  <footer>
    some stuff here
  </footer>
  <!-- ========== END FOOTER ========== -->

  <!-- ========== SECONDARY CONTENTS ========== -->
  <!-- Account Sidebar Navigation -->

  <!-- End Account Sidebar Navigation -->
  <!-- ========== END SECONDARY CONTENTS ========== -->
  <!-- autocomplete -->
  <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
  <script type="text/javascript" src="{% static 'assets/autocomplete/jquery.init.js' %}"></script>
  <script type="text/javascript" src="{% static 'assets/autocomplete/jquery-3.4.1.min.js' %}"></script>
  <script type="text/javascript" src="{% static 'assets/autocomplete/jquery.post-setup.js' %}"></script>
  <script type="text/javascript" src="{% static 'assets/autocomplete/autocomplete.init.js' %}"></script>
  <script type="text/javascript" src="{% static 'assets/autocomplete/forward.js' %}"></script>
  <script type="text/javascript" src="{% static 'assets/autocomplete/select2.js' %}"></script>

  <!-- JS Global Compulsory -->
  <script src="{% static 'assets/vendor/jquery/dist/jquery.js' %}"></script>
  <script src="{% static 'assets/vendor/jquery/dist/jquery.min.js' %}"></script>
  <script src="{% static 'assets/vendor/jquery-migrate/dist/jquery-migrate.min.js' %}"></script>
  <script src="{% static 'assets/vendor/popper.js/dist/umd/popper.min.js' %}"></script>
  <script src="{% static 'assets/vendor/bootstrap/bootstrap.min.js' %}"></script>

  {{ form.media }}

</body>
</html>

views.py

class SchoolAutocomplete(autocomplete.Select2QuerySetView):
    def get_queryset(self):
        qs = Schools.objects.all()

        if self.q:
            qs = qs.filter(name__istartswith=self.q)
        return qs

forms.py

class StudentAssignmentForm(forms.ModelForm):

    class Meta:
        model = StudentAssignment

        fields = (
            'subject', 
            'level',
            'grade',
            'school',
            'frequency',
            )
        widgets = {'school': autocomplete.ModelSelect2(url='school-autocomplete')}

        exclude = ('user',)
jpic commented 4 years ago

STATICFILES_DIRS are used to populate STATIC_ROOT, you should configure you server to serve STATIC_ROOT on STATIC_URL in production or use whitenoise.

Also, why prefix your static files paths with assets/ ?

If confused, try this article which un-confused a bunch of users on stackoverflow:

https://blog.yourlabs.org/posts/2012-08-28-surviving-djangocontribstaticfiles-or-how-to-manage-static-files-with-django/

Cesar48 commented 3 years ago

I have a similar problem, for some reason the templates try to render something based on static files in {{STATIC_ROOT}}/admin/js/vendor/select2, but this folder does not exist (similar things appear to happen for css and img instead of js). If the files are present in these folders everything works perfectly fine, but collectstatic does not put them here. Findstatic shows the files specified don't exist. Some folder searching revealed that there are in fact static folders in the packages, and these probably are collected, but none of them contain the word admin so this is probably where it breaks.

I'm on 3.8.1 btw, but looking at changelogs that should have no major differences from most recent version (3.8.2).

jilljenn commented 2 years ago

Same here.

jpic commented 2 years ago

the templates try to render something based on static files in {{STATIC_ROOT}}/admin/js/vendor/select2, but this folder does not exist

Do you have django.contrib.admin in INSTALLED_APPS? Because the files are there: https://github.com/django/django/tree/main/django/contrib/admin/static/admin/js/vendor/select2

jilljenn commented 2 years ago

Thanks for the fast reply. It is, but for some reason collectstatic didn't add them, so I had to put a copy of django-autocomplete-light in my static folder.

jpic commented 2 years ago

Do you have django.contrib.admin in INSTALLED_APPS? Because collectstatic will copy them from django.contrib.admin if you have that in INSTALLED_APPS