geex-arts / django-jet

Modern responsive template for the Django admin interface with improved functionality. We are proud to announce completely new Jet. Please check out Live Demo
https://github.com/jet-admin/jet-bridge
GNU Affero General Public License v3.0
3.58k stars 773 forks source link

Autocomplete with Custom queryset #151

Open a1Gupta opened 7 years ago

a1Gupta commented 7 years ago

In docs, its mentioned that -

Autocomplete is nice, but sometimes you don’t want this behaviour (e.x. because you want to limit the provided queryset for a particular widget). In this case you can disable autocompletion.

Then how to deal with large tables, with custom queryset. How are you handling this issue ? Is there any workaround for this ?

Edit: I tried to use django autocomplete light for autocompletion with custom queryset. But it's showing two select dropdown widgets. screenshot from 2016-11-27 17 46 00 How can I fix these widgets ?

tityrus commented 7 years ago

If you work your way through the code of Jet, you can make some overrides yourself. However, it would be good to see support included.

I propose this code as a replacement for the jet/forms.py lookup function:

`

def lookup(self):

if self.cleaned_data['q']:

    if getattr(self.model_cls, 'autocomplete_search_fields') and getattr(self.model_cls, 'autocomplete_search_query'):
        raise Exception("The model cannot have both an autocomplete_search_fields and autocomplete_search_query function.")

    elif getattr(self.model_cls, 'autocomplete_search_query'):
        qs = self.model_cls.autocomplete_search_query(self.cleaned_data['q'])

    elif getattr(self.model_cls, 'autocomplete_search_fields'):
        qs = self.model_cls.objects
        search_fields = self.model_cls.autocomplete_search_fields()
        filter_data = [Q((field + '__icontains', self.cleaned_data['q'])) for field in search_fields]
        qs = qs.filter(reduce(operator.or_, filter_data))

else:
    qs = self.model_cls.objects.none()

limit = self.cleaned_data['page_size'] or 100
page = self.cleaned_data['page'] or 1
offset = (page - 1) * limit

items = list(map(lambda instance: {
    'id': instance.pk,
    'text': get_model_instance_label(instance)
}, qs.all()[offset:offset + limit]))
total = qs.count()

return items, total

` This way you could define a autocomplete_search_query function in your models.

jackboot7 commented 7 years ago

@jorisvd Any idea on how to pass a queryset defined in the formfield_for_foreignkey method for that form?

Reading on jet's code, it seems that one must override the ModelLookupForm and the corresponding view, for each model to add a custom queryset, but it doesn't seems very practical.

tolomea commented 7 years ago

Ideally you want support for both formfield_for_foreignkey and autocomplete_search_query as they serve different needs. The first is often used for filtering specific to the model and field doing the linking. For example a default choice field on the example polls model would want to filter to choices belonging to the current poll. The second is often used for generic filtering or queryset performance stuff, so soft delete support, or pulling in related tables required to construct the str representation.

SalahAdDin commented 7 years ago

@f1nality

Ismael-VC commented 7 years ago

Please come to the django-jet Discord server so we can organize if you like:

Welcome! 😄

abdulwahid24 commented 6 years ago

I am using formfield_for_foreignkey in modeladmin to create custom queryset but it's not reflecting on autocomplete as the lookup is fetching all records.

abdulwahid24 commented 6 years ago

@joristdma Your solution looks promised but little bit confuse as making changes directly on the library isn't a good idea so is there any way where I can override this functionality. Thanks

tityrus commented 6 years ago

@abdulwahid24 I would like to make some pull requests but is this repository still being maintained? I am not seeing any new releases. If the author can comment he is alive then I can make PR's.

abdulwahid24 commented 6 years ago

@joristdma I do agree with you. I checked there FB, Linkedin, Github but they are not active for last couple of months.

tityrus commented 6 years ago

@abdulwahid24 I sent out a message through the contact form on the commercial website. No reply.

SalahAdDin commented 6 years ago

@abdulwahid24 @joristdma Can you make a PR in jet_community fork?

tityrus commented 6 years ago

*jet-community https://github.com/jet-community/django-jet

abdulwahid24 commented 6 years ago

Hi @joristdma, I checked the above fork but its release version is very behind to the original one.

tityrus commented 6 years ago

@abdulwahid24 @SalahAdDin Does it make sense to create yet another fork? Will we be able to maintain it? If someone wants to organize the new fork and edit the README and maybe some configuration files, I can make the PR's for a couple of features and bugs.

SalahAdDin commented 6 years ago

@joristdma These fork is our fork, make your PR and we will review it and merge it, if you want mantain it, your welcome.

abdulwahid24 commented 6 years ago

@SalahAdDin Are you maintaining geex-arts/django-jet original repo? If yes then I would suggest you to be more active because there are people who are investing their effort in order to improve the django-jet but no is responding to accept their PR and issues.

jackboot7 commented 6 years ago

@abdulwahid24 As I understand from @SalahAdDin reply he is mantaining jet-community/django-jet fork. I think he is open to PRs/Issues down in jet-community/django-jet.

abdulwahid24 commented 6 years ago

@SalahAdDin I see the release version on jet-community/django-jet is very behind as compare to the parent repo, I am not sure whether jet-community/django-jet has all previous features and fixes from the parent repo.

abdulwahid24 commented 6 years ago

@SalahAdDin I think your fork is not up to date as its not supporting django 1.11 as I am getting the below error.

    urlconf_module = import_module(urlconf_module)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/jet/urls.py", line 2, in <module>
    from django.conf.urls import patterns, url
ImportError: cannot import name 'patterns'
SalahAdDin commented 6 years ago

@abdulwahid24 these version is very ahead, is updated, many PR was merged, and etc. Leave me see about this problem, because i think we did solved these problems before.

Can you see @abdulwahid24 https://github.com/jet-community/django-jet/blob/master/jet/urls.py? You have to install it from github.

abdulwahid24 commented 6 years ago

@SalahAdDin I installed from the release tag (https://github.com/jet-community/django-jet/archive/0.1.5.zip) like pip install https://github.com/jet-community/django-jet/archive/0.1.5.zip and then I am getting the below mentioned error.

Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7f17de10f048>
Traceback (most recent call last):
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 125, in inner_run
    self.check(display_num_errors=True)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/core/management/base.py", line 359, in check
    include_deployment_checks=include_deployment_checks,
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/core/management/base.py", line 346, in _run_checks
    return checks.run_checks(**kwargs)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/core/checks/registry.py", line 81, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/core/checks/urls.py", line 16, in check_url_config
    return check_resolver(resolver)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/core/checks/urls.py", line 26, in check_resolver
    return check_method()
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/urls/resolvers.py", line 254, in check
    for pattern in self.url_patterns:
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/urls/resolvers.py", line 405, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/urls/resolvers.py", line 398, in urlconf_module
    return import_module(self.urlconf_name)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/abdulw/workspace/SynDashboard/SynDashboard/urls.py", line 27, in <module>
    url(r'^jet/', include('jet.urls', 'jet')),
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/django/conf/urls/__init__.py", line 50, in include
    urlconf_module = import_module(urlconf_module)
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/abdulw/workspace/SynDashboard/.env/lib/python3.6/site-packages/jet/urls.py", line 2, in <module>
    from django.conf.urls import patterns, url
ImportError: cannot import name 'patterns'
SalahAdDin commented 6 years ago

Ok, because these release is old, we didn't release a new version yet. You have to install from master branch. Maybe the documentation is wrong now.

abdulwahid24 commented 6 years ago

Then I install by pip install git+https://github.com/jet-community/django-jet.git, Its working fine. Now I think @joristdma you should submit your PRs on jet-community's django-jet

SalahAdDin commented 6 years ago

@abdulwahid24 I'm glad to hear it.

abdulwahid24 commented 6 years ago

@joristdma Any update about your PRs request on jet-community's django-jet

SalahAdDin commented 6 years ago

@joristdma @abdulwahid24 I'm waiting for it.

tityrus commented 6 years ago

@abdulwahid24 @SalahAdDin No, I didn't proceed because there doesn't seem to be any fork which is up-to-date and properly maintained?

abdulwahid24 commented 6 years ago

@joristdma I think this fork https://github.com/jet-community/django-jet is up-to-date as @SalahAdDin is maintaining it.

SalahAdDin commented 6 years ago

Yes, i'm trying.

abdulwahid24 commented 6 years ago

@SalahAdDin I would request you to make the latest release because everyone looks at last release on your fork.

tityrus commented 6 years ago

I'll try to make those changes within 2 weeks or so. @SalahAdDin if you find the time, maybe you can update the repo to the latest version by then.

tityrus commented 6 years ago

@SalahAdDin @abdulwahid24 I implemented this feature in a new fork from the latest master of django-jet. You can find the repo here: https://github.com/tityrus/django-jet . Master branch. You can find more info in the last few commit messages there. Basically it works like this: in your model, instead of the autocomplete_search_fields, create a method autocomplete_search_query that returns a queryset. The arguments passed to the function are the search query string and the user object. So your function definition can be: def autocomplete_search_query(self, q, user):.

abdulwahid24 commented 6 years ago

@tityrus @SalahAdDin I see Django 2.0 added support for autocomplete_fields

SalahAdDin commented 6 years ago

@abdulwahid24 Really?

gotounix commented 6 years ago

@a1Gupta Do you fix this problem? I have the same problem while using django-autocomplete-light. There are two dropdown select fields, how to fix it?