Skip to content

Instantly share code, notes, and snippets.

@solace
Created January 3, 2021 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save solace/d3ef0050c22bfe26b5a2eae842006704 to your computer and use it in GitHub Desktop.
Save solace/d3ef0050c22bfe26b5a2eae842006704 to your computer and use it in GitHub Desktop.
django-addanother with django-autocomplete-light and GenericForeignKeys
# Source: https://github.com/yourlabs/django-autocomplete-light/blob/master/test_project/select2_generic_foreign_key/admin.py
import json
from django.contrib import admin
from django.contrib.admin.options import IS_POPUP_VAR, TO_FIELD_VAR
from django.contrib.contenttypes.models import ContentType
from django.template.response import TemplateResponse
from .forms import TForm
from .models import TModel
class TestAdmin(admin.ModelAdmin):
form = TForm
# Source: https://github.com/django/django/blob/fed8129276eac973fd48a2f33b7e1735a866628d/django/contrib/admin/options.py#L1175
# Extend response_add to customise popup handling.
def response_add(self, request, obj, post_url_continue=None):
if IS_POPUP_VAR not in request.POST:
return super().response_add(request, obj, post_url_continue)
else:
"""
Determine the HttpResponse for the add_view stage.
"""
opts = obj._meta
to_field = request.POST.get(TO_FIELD_VAR)
if to_field:
attr = str(to_field)
else:
attr = obj._meta.pk.attname
value = obj.serializable_value(attr)
ctype = ContentType.objects.get_for_model(obj)
popup_response_data = json.dumps({
# KEY LINE: Ensure ctype is returned as part of the value
'value': '%s-%s' % (ctype.id, value),
'obj': str(obj),
})
return TemplateResponse(request, self.popup_response_template or [
'admin/%s/%s/popup_response.html' % (opts.app_label, opts.model_name),
'admin/%s/popup_response.html' % opts.app_label,
'admin/popup_response.html',
], {
'popup_response_data': popup_response_data,
})
admin.site.register(TModel, TestAdmin)
from dal import autocomplete
from dal_select2_queryset_sequence.views import Select2QuerySetSequenceView
from dal_select2_queryset_sequence.widgets import QuerySetSequenceSelect2
from django.contrib.auth.models import Group
from .models import TModel
from .widgets import AddAnotherWidgetWrapper
class TForm(autocomplete.FutureModelForm):
# Either of these ModelFields work fine.
test = autocomplete.Select2GenericForeignKeyModelField(
model_choice=[
(Group, 'name'),
(TModel, 'name', [('name', 'name')])
], # Model with values to filter
required=False,
field_id='test',
)
test2 = autocomplete.GenericForeignKeyModelField(
model_choice=[(Group,), (TModel,)],
required=False,
widget=QuerySetSequenceSelect2,
view=Select2QuerySetSequenceView,
)
# ADD THIS
# Note: Only tested for admin forms.
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['test'].widget = (
AddAnotherWidgetWrapper(
self.fields['test'].widget,
reverse_lazy('[THE ADMIN ADD LINK]')
)
)
class Meta:
model = TModel
fields = ('name',)
from django_addanother.widgets import AddAnotherWidgetWrapper as AddAnother
class AddAnotherWidgetWrapper(AddAnother):
def __init__(self, widget, add_related_url, add_icon=None):
# ADD THIS: Need to set self.choices or it will error
self.choices = widget.choices
super().__init__(
widget, add_related_url, add_icon
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment