Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to display data from a model in another app #1196

Open
gamesbook opened this issue Oct 30, 2020 · 20 comments
Open

Unable to display data from a model in another app #1196

gamesbook opened this issue Oct 30, 2020 · 20 comments

Comments

@gamesbook
Copy link

Django 1.11

DAL works well when dislalying data from a model within the same app; however, I cannot get it work when used in another app in the same project.

urls.py (research app):

    url(r'^domain-auto',
        auto.DomainAutocomplete.as_view(),
        name='domain-auto'),

Browser:
http://127.0.0.1:8000/research/domain-auto?q=KN00

Results:

{
"results": [
    {
    "id": "5265",
    "text": "KN0005:One
    "selected_text": "abc"
    },
    {
    "id": "5266",
    "text": "KN0006:Two",
    "selected_text": "def"
    },
 ]

In main urls.py:

  url(r'^research/', include('research.urls')),

In another app...

Form definition:

    class Meta:
        model = models.TestModelName
        fields = '__all__'
        widgets = {
            'domain': autocomplete.ModelSelect2(
                url="research:domain-auto"),
        }

However the widget is not rendered as a normal autocomplete widget and no data is showing for it

I have also tried:

    domain = forms.ModelChoiceField(
        queryset=Domain.objects.all(),
        widget=autocomplete.ModelSelect2(url='research:domain-auto')
    )

in the form definition, but this has the same outcome.

@darahsten
Copy link

Is your problem with the widget or it is with displaying data from another app? I suspect the widget is the problem. Please check that you have loaded the relevant media. Also, you need to specify which frontend you are using. DAL has some incompatibilities with Materialize. Lastly, the information you have provided is not sufficient for anyone to reproduce or understand your issue.

@gamesbook
Copy link
Author

If the information provided is insufficient to understand what I have done (the extracts I provided are similar to those shown in the DAL tutorial), please let me know what is missing. I am working with the Django admin, with Django Suit as the "skin".

The settings.py file contains these entries in INSTALLED_APPS:

    'dal',
    'dal_select2',
    'dal_legacy_static',

Some additional info is the loading sequence of files at startup:

[30/Oct/2020 14:38:22] "GET /static/admin/css/vendor/select2/select2.css HTTP/1.1" 200 17604
[30/Oct/2020 14:38:22] "GET /static/autocomplete_light/autocomplete_light.js HTTP/1.1" 200 16365
[30/Oct/2020 14:38:22] "GET /static/autocomplete_light/select2.js HTTP/1.1" 200 4018
[30/Oct/2020 14:38:22] "GET /static/autocomplete_light/i18n/en.js HTTP/1.1" 200 925
[30/Oct/2020 14:38:22] "GET /static/admin/js/vendor/select2/select2.full.js HTTP/1.1" 200 161832

I agree it it seems to be widget that is not working as expected (I thought it was working before) - but how would I go about finding what is causing it to fail?

@gamesbook
Copy link
Author

I tried testing this in a separate project (in case it was a issue with, for example Django Suit) - but there are no problems with that - see https://github.com/gamesbook/django-suit (autocomplete used on the Cities form).

However, on checking the developer console for my project, it seems there is an issue with jQuery. Which version should be in use?

jquery_error

@darahsten
Copy link

I am not sure, which version of JQuery are you using. I believe the latest version should work fine. I am guessing what you to question is how to ensure that JQuery is included in the admin side of Django for autocomplete light to work. In case there is no implicit way - Which I am sure there is. You can override this templatehttps://github.com/django/django/blob/master/django/contrib/admin/templates/admin/base.html if you know how to . Then include the JQuery there in.

@gamesbook
Copy link
Author

I have tried installing the latest jQuery; it gets loaded before autocomplete:

[31/Oct/2020 13:44:59] "GET /static/site/js/jquery-3.5.1.js HTTP/1.1" 304 0
[31/Oct/2020 13:44:59] "GET /static/autocomplete_light/select2.css HTTP/1.1" 200 267
[31/Oct/2020 13:44:59] "GET /static/autocomplete_light/autocomplete_light.js HTTP/1.1" 200 16365
[31/Oct/2020 13:44:59] "GET /static/admin/css/vendor/select2/select2.css HTTP/1.1" 200 17604
[31/Oct/2020 13:44:59] "GET /static/autocomplete_light/select2.js HTTP/1.1" 200 4018
[31/Oct/2020 13:44:59] "GET /static/admin/js/vendor/select2/select2.full.js HTTP/1.1" 200 161832
[31/Oct/2020 13:44:59] "GET /static/autocomplete_light/i18n/en.js HTTP/1.1" 200 925

However, select itself now throws a read property error:

dal_undefined

The en.js error:

select2_error

@jpic
Copy link
Member

jpic commented Oct 31, 2020

Are you using DAL 3.8.1 ?

@danielmorell isn't jQuery part of the built bundle now ?

@gamesbook
Copy link
Author

gamesbook commented Oct 31, 2020

I am using 3.8.1 for the test (referred to as "separate project" above) and in the project that is currently failing. Although the actual project is obviously bigger and more complex I am trying to understand what the differences are that could be causing this.

@jpic
Copy link
Member

jpic commented Oct 31, 2020

@gamesbook can we have template and view code too please ? for both cases (where it work and where it doesnt)

@gamesbook
Copy link
Author

I am not allowed to post the full template code, but can post the header section.

The working case is at https://github.com/gamesbook/django-suit - see https://github.com/gamesbook/django-suit/blob/v2/demo/demo/views.py (but there is no template change as such).

I don't store the autocomplete processing code in views.py but in differently named file called auto.py. It contains this code:

from dal import autocomplete  # WAS autocomplete-light
from django.db.models import Q
from .models import  Selection

class SelectionNameAutocomplete(autocomplete.Select2QuerySetView):

    def get_queryset(self):
        qs = Selection.objects.all()
        if self.q:
            qs = qs.filter(name__icontains=self.q)
        return qs

The base template contains:

{% extends 'admin/base.html' %}
{% load i18n suit_tags admin_static  %}

{% block title %}
  {{ title }} | {{ site_title|default:_('Project admin') }}
{% endblock %}

{% block branding %}
<h1 id="site-name">
  <a href="{% url 'admin:index' %}">
    {{ site_header|default:_('Project administration') }}
    <span class="header-label">{% trans 'Admin' %}</span>
  </a>
</h1>
{% endblock %}

{% block extrahead %}{{ block.super }}
<!-- https://github.com/yourlabs/django-autocomplete-light/issues/1196 -->
<script  type="text/javascript" src="/static/site/js/jquery-3.5.1.js"></script>
{% endblock %}

<script src="/static/suit/js/suit.js"></script>
<script type="text/javascript">
    Suit.ListActionsToggle.init();
</script>

<!-- custom JS code follows this ... -->

There is no other custom template being used; rendering happens through the normal built-in admin templates.

@jpic
Copy link
Member

jpic commented Oct 31, 2020

I don't see the form rendering code, nor the view that's supposed to render the form in its initial state.

But maybe {{ block.super }} is what's supposed to load {{ form.media }}, so jquery.js script should be before that line.

Did you try without your jquery script tag at all ? I don't see it in the demo, maybe django-suit already loads its own.

@gamesbook
Copy link
Author

The code for the form is this:

class TestModelForm(forms.ModelForm):

    class Meta:
        model = models.TestModelName
        fields = '__all__'
        widgets = {
            'domain': autocomplete.ModelSelect2(
                url="core:domain-auto"),
        }

There is no specific view code to render the form as that is handled by Django admin.

I have tried changing the load order for jquery.js but it makes no difference.

If I do not use jQuery, I now get the error shown in my 3rd message of this thread.

@gamesbook
Copy link
Author

gamesbook commented Nov 1, 2020

Update: I tried reverting to an earlier version of DAL - 3.4.1 - and that works as expected. Manually adding in the jQuery library is not needed.

The README says:
Django 1.11 (LTS), is supported until django-autocomplete-light-3.2.10

But perhaps the DAL version can be bumped up to show the most recent that will still work?

@danielmorell
Copy link
Contributor

danielmorell commented Nov 3, 2020

@danielmorell isn't jQuery part of the built bundle now ?

Sorry for the late response. @jpic we are still using jQuery supplied by Django. So on pages where jQuery is not loaded by Django by default it will need to be included. The reason is that if a developer wants to replace the default jQuery with a specific version, or Django provides a copy to the view, we don't want to duplicate what we are loading. It also complicates using it with Select2. If Select2 is instantiated as an object method on one instance of jQuery and our Select2 function uses another instance of jQuery, it will fail.

@gamesbook the first error you encountered was caused by not having jQuery loaded in the browser for the view. I believe you discovered this already. The second error (where we ironically discover 'defined' is undefined) is caused because Select2 has not been initialized yet.

What is the 'init' of undefined error on index:2542? Is it related to Select2, dal, or something else?

More details about the cause

In the following code where we invoke dalLoadLanguage() because of the load/execution order django.jQuery.fn.select2.amd is undefined.

if (typeof dalLoadLanguage !== 'undefined') {
dalLoadLanguage($);
} else {
document.addEventListener('dal-language-loaded', function (e) {
// `e.lang` is the language that was loaded.
dalLoadLanguage($);
})
}

We are passing in django.jQuery as the value of argument e when we invoke dalLoadLanguage().

I believe the root cause is this... dalLoadLanguage() is being called from autocomplete_light/autocomplete_light.js without regard for when /static/admin/js/vendor/select2/select2.full.js is loaded.

@jpic The dalLoadLanguage() function is only used by dal_select2, I think I can fix this issue by moving the place where the dalLoadLanguage() function is invoked to inside the initialize() method, since django.jQuery.fn.select2.amd should be defined at that point.

This also might require that we only load languages once per autocomplete handling function. I will have to think about the repercussions of this a little more. I don't think it will change the API for developers, but may change how initializations are handled and tracked internally.

Also, the language files are Select2 specific and should probably be moved from dal to dal_select2. I think I put them in dal when I first updated the JS because I didn't know any better.

@jpic
Copy link
Member

jpic commented Nov 4, 2020

@gamesbook

But perhaps the DAL version can be bumped up to show the most recent that will still work?

Yes, you may keep the README updated for others, but our policy is to support the latest versions because tdd makes it easy to update confidently

@danielmorell
Thank you for the great explanation, do you think there is a workaround meanwhile ?

Other solutions could be:

a) Perhaps we could add a jQuery with noconflict to the bundle ?

b) maybe not using form.media at all ? then we'd just be answering to people who forget to add the static scripts in their templates but that's a lot easier to see coming at a thousand miles distance.

c) choices "similar to select2 but without jquery"

We are passing in django.jQuery as the value of argument e when we invoke dalLoadLanguage()

Probably worth renaming that argument for posterity ?

@gamesbook
Copy link
Author

Yes, you may keep the README updated for others, but our policy is to support the latest versions because tdd makes it easy to update confidently

Not sure who "you" is? A project team member will need to do this.

@jpic
Copy link
Member

jpic commented Nov 6, 2020

Someone who has a live and running version with 1.11 can clicking the edit link on the file, but it will need a project member to merge for sure.

We can't ask our project members to manually verify 1.11, we've already got plenty on our hands, hopefully situation should improve once we offer the webcomponent but that's planned for the following months so we're trying to hang on until then.

@jpic
Copy link
Member

jpic commented Nov 6, 2020

@gamesbook Could you try removing the "research:" and "core:" prefixes of your urls ?

Could you paste the output HTML ? Including the data- attributes particularly.

It doesn't look like namespaces are properly configured, it would be nice to know that it also doesn't work without namespaces.

While I use namespaces in Django urls myself, I'm not sure why they are so tricky and require to "repeat yourlself". For a namespace to work you need to:

  1. specify it in the url include
  2. specify the same in the urlconf that is included

Otherwise I don't think it will work, unless the situation has much improved since last time I checked. I wouldn't know because I don't manage URLs myself anymore, I let CRUDLFA+ do the job and it does setup nice namespaces for me by itself.

Thank you for your patience

@gamesbook
Copy link
Author

Given that DAL "just worked" when I switched to an earlier version, I am unsure why you suggest all these changes?

@jpic
Copy link
Member

jpic commented Nov 10, 2020

I think that there is a mistake in your URL configuration.

@gamesbook
Copy link
Author

Why would an incorrect URL mean that an earlier version works? What has changed to cause this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants