Django: AJAX ManyToManyField in admin

后端 未结 3 1879
礼貌的吻别
礼貌的吻别 2021-02-10 03:19

I want to display ManyToManyFields in admin just like filter_horizontal does, but populate the options as the user types into the filter field. There a

3条回答
  •  情深已故
    2021-02-10 03:37

    I started from your code and I used a custom javascript to retrieve values from photologue Photo model; please note that I'm using grappelli and the Django url that get the json object is hardcoded; also the field in my model is called "photos":

    # urls.py
    url(r'^get_json_photos/(?P[\w-]+)/$', 'catalogo.views.get_json_photos', name='get_json_photos'),
    
    
    # views.py    
    from photologue.models import Photo
    from django.utils import simplejson as json
    
    def get_json_photos(request, query):
        photos = Photo.objects.filter(title__icontains=query)[:20]
        p = [ {"name":photo.title, "id":photo.id} for photo in photos ]
        response = json.dumps(p)
        return HttpResponse(response, mimetype="application/json")
    
    
    # admin.py
    from django.conf import settings
    from django.contrib.admin.widgets import FilteredSelectMultiple
    
    class MyFilteredSelectMultiple(FilteredSelectMultiple):
    
        class Media:
            js = (settings.ADMIN_MEDIA_PREFIX + "js/core.js",
                  settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js",
                  settings.ADMIN_MEDIA_PREFIX + "js/SelectFilter2.js",
                  settings.MEDIA_URL + "js/ajax_photo_list.js")
    
    
    class MyModelMultipleChoiceField(ModelMultipleChoiceField):
    
        def clean(self, value):
            return [val for val in value]
    
    
    class GalleryForm(forms.ModelForm):
        photos = MyModelMultipleChoiceField(queryset=Photo.objects.none(), required=False,
            widget=MyFilteredSelectMultiple(verbose_name="photos", is_stacked=False))
    
        def __init__(self, *args, **kwargs):
            super(GalleryForm, self).__init__(*args, **kwargs)
            try:
                i = kwargs["instance"]
                gallery = Gallery.objects.get(pk=i.pk)
                qs = gallery.photos.all()
            except:
                qs = Photo.objects.none()
            self.fields['photos'].queryset = qs
    
        class Meta:
            model = Gallery
            widgets = {
                'photos': MyFilteredSelectMultiple(verbose_name="photos", is_stacked=False)
            }
    
    
    class GalleryAdmin(admin.ModelAdmin):
        list_display = ('title', 'date_added', 'photo_count', 'is_public')
        list_filter = ['date_added', 'is_public']
        date_hierarchy = 'date_added'
        prepopulated_fields = {'title_slug': ('title',)}
        filter_horizontal = ()
        form = GalleryForm
    
    
    # ajax_photo_list.js 
    (function($){
    $("#id_photos_input").live("keyup", function(){
        var querystring = $("#id_photos_input").val();
        if (querystring) {
            $.ajax ({
                type: "GET",
                url: "/get_json_photos/"+querystring+"/",
                cache: false,
                success: function(json) {
                    if (json) {
                        var list_from = $("#id_photos_from option").map(function() {
                            return parseInt($(this).val());
                        });
                        var list_to = $("#id_photos_to option").map(function() {
                            return parseInt($(this).val());
                        });
                        for (var pid in json) {
                            if ($.inArray(json[pid].id, list_from) == -1 && $.inArray(json[pid].id, list_to) == -1) {
                                $("#id_photos_from").prepend("");
                            }
                        }
                        SelectBox.init('id_photos_from');
                        SelectBox.init('id_photos_to');
                    }
                }
            });
        }
    })
    }(django.jQuery));
    

    I'm thinking to make it generic, since is not the first time that I have this problem,

提交回复
热议问题