mirror of
https://github.com/postgres/pgweb.git
synced 2025-08-13 13:12:42 +00:00
Implement auto-complete for /admin/ forms that reference User
We have so many users now that loading these forms take forever. Instead, implement a textbox with autocomplete using django-selectable, which will not load the whole list of users at once.
This commit is contained in:
@ -1,5 +1,27 @@
|
|||||||
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from selectable.forms.widgets import AutoCompleteSelectWidget
|
||||||
|
|
||||||
|
from pgweb.core.lookups import UserLookup
|
||||||
|
|
||||||
from models import Contributor, ContributorType
|
from models import Contributor, ContributorType
|
||||||
|
|
||||||
|
class ContributorAdminForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Contributor
|
||||||
|
exclude = ()
|
||||||
|
widgets = {
|
||||||
|
'user': AutoCompleteSelectWidget(lookup_class=UserLookup),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ContributorAdminForm, self).__init__(*args, **kwargs)
|
||||||
|
self.fields['user'].widget.can_add_related = False
|
||||||
|
self.fields['user'].widget.can_change_related = False
|
||||||
|
|
||||||
|
class ContributorAdmin(admin.ModelAdmin):
|
||||||
|
form = ContributorAdminForm
|
||||||
|
|
||||||
admin.site.register(ContributorType)
|
admin.site.register(ContributorType)
|
||||||
admin.site.register(Contributor)
|
admin.site.register(Contributor, ContributorAdmin)
|
||||||
|
@ -1,14 +1,33 @@
|
|||||||
|
from django import forms
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from selectable.forms.widgets import AutoCompleteSelectMultipleWidget
|
||||||
|
|
||||||
from pgweb.core.models import Version, OrganisationType, Organisation
|
from pgweb.core.models import Version, OrganisationType, Organisation
|
||||||
from pgweb.core.models import ImportedRSSFeed, ImportedRSSItem
|
from pgweb.core.models import ImportedRSSFeed, ImportedRSSItem
|
||||||
from pgweb.core.models import ModerationNotification
|
from pgweb.core.models import ModerationNotification
|
||||||
|
|
||||||
|
from pgweb.core.lookups import UserLookup
|
||||||
|
|
||||||
|
class OrganisationAdminForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Organisation
|
||||||
|
exclude = ()
|
||||||
|
widgets = {
|
||||||
|
'managers': AutoCompleteSelectMultipleWidget(lookup_class=UserLookup),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(OrganisationAdminForm, self).__init__(*args, **kwargs)
|
||||||
|
self.fields['managers'].widget.can_add_related = False
|
||||||
|
self.fields['managers'].widget.can_change_related = False
|
||||||
|
self.fields['managers'].widget.can_delete_related = False
|
||||||
|
|
||||||
class OrganisationAdmin(admin.ModelAdmin):
|
class OrganisationAdmin(admin.ModelAdmin):
|
||||||
|
form = OrganisationAdminForm
|
||||||
list_display = ('name', 'approved', 'lastconfirmed',)
|
list_display = ('name', 'approved', 'lastconfirmed',)
|
||||||
list_filter = ('approved',)
|
list_filter = ('approved',)
|
||||||
ordering = ('name', )
|
ordering = ('name', )
|
||||||
filter_horizontal = ('managers', )
|
|
||||||
search_fields = ('name', )
|
search_fields = ('name', )
|
||||||
|
|
||||||
class VersionAdmin(admin.ModelAdmin):
|
class VersionAdmin(admin.ModelAdmin):
|
||||||
|
25
pgweb/core/lookups.py
Normal file
25
pgweb/core/lookups.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from django.contrib.auth.models import User
|
||||||
|
from selectable.base import ModelLookup
|
||||||
|
from selectable.registry import registry
|
||||||
|
from selectable.decorators import staff_member_required
|
||||||
|
|
||||||
|
|
||||||
|
@staff_member_required
|
||||||
|
class UserLookup(ModelLookup):
|
||||||
|
model = User
|
||||||
|
search_fields = (
|
||||||
|
'username__icontains',
|
||||||
|
'first_name__icontains',
|
||||||
|
'last_name__icontains',
|
||||||
|
)
|
||||||
|
filters = {'is_active': True, }
|
||||||
|
|
||||||
|
def get_item_value(self, item):
|
||||||
|
# Display for currently selected item
|
||||||
|
return u"%s (%s)" % (item.username, item.get_full_name())
|
||||||
|
|
||||||
|
def get_item_label(self, item):
|
||||||
|
# Display for choice listings
|
||||||
|
return u"%s (%s)" % (item.username, item.get_full_name())
|
||||||
|
|
||||||
|
registry.register(UserLookup)
|
@ -98,6 +98,7 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django_markwhat',
|
'django_markwhat',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'pgweb.selectable',
|
||||||
'pgweb.core',
|
'pgweb.core',
|
||||||
'pgweb.mailqueue',
|
'pgweb.mailqueue',
|
||||||
'pgweb.account',
|
'pgweb.account',
|
||||||
|
@ -135,6 +135,9 @@ urlpatterns = patterns('',
|
|||||||
# Uncomment the next line to enable the admin:
|
# Uncomment the next line to enable the admin:
|
||||||
(r'^admin/', include(admin.site.urls)),
|
(r'^admin/', include(admin.site.urls)),
|
||||||
|
|
||||||
|
# We use selectable...
|
||||||
|
(r'^selectable/', include('selectable.urls')),
|
||||||
|
|
||||||
# This should not happen in production - serve by the webserver natively!
|
# This should not happen in production - serve by the webserver natively!
|
||||||
url(r'^(favicon.ico)$', 'django.views.static.serve', {
|
url(r'^(favicon.ico)$', 'django.views.static.serve', {
|
||||||
'document_root': 'media',
|
'document_root': 'media',
|
||||||
|
@ -1,2 +1,16 @@
|
|||||||
{%extends "admin/base.html"%}
|
{%extends "admin/base.html"%}
|
||||||
{%block branding%}Welcome to the PostgreSQL website administration site | <b><a href="/admin/pending/">Pending</a></b> moderation | <b><a href="/admin/purge/">Purge</a></b> from frontend{%endblock%}
|
{%block branding%}Welcome to the PostgreSQL website administration site | <b><a href="/admin/pending/">Pending</a></b> moderation | <b><a href="/admin/purge/">Purge</a></b> from frontend{%endblock%}
|
||||||
|
|
||||||
|
{%block extrahead%}
|
||||||
|
<link rel="stylesheet" href="/media/css/jquery-ui.css" type="text/css">
|
||||||
|
<link href="/media/selectable/css/dj.selectable.css" type="text/css" media="all" rel="stylesheet">
|
||||||
|
<script src="/media/js/jquery.min.js"></script>
|
||||||
|
<script src="/media/js/jquery-ui.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/media/selectable/js/jquery.dj.selectable.js"></script>
|
||||||
|
<style>
|
||||||
|
ul.selectable-deck li.selectable-deck-item a.selectable-deck-remove {
|
||||||
|
float: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{%endblock%}
|
||||||
|
Reference in New Issue
Block a user