Множество запросов Django Limit ManytoMany на основе выбранного FK

У меня есть модель, которая выглядит так:

class Invite(models.Model):
    user = models.ForeignKey(User)
    event = models.ForeignKey(Event)
    roles = models.ManyToManyField(Role, blank=True, null=True)
    sent =  models.BooleanField("Invite Sent", default=False, editable=False)
    created = models.DateTimeField(auto_now_add=True)

    def __unicode__(self):
        return u"%s" % self.user

    class Meta:
        unique_together =(('user','event'),)


class Role(models.Model):
    """
    This associates a user role to an event
    """
    event = models.ForeignKey(Event, related_name="roles")
    roletype = models.ForeignKey(RoleType)
    profiles = models.ManyToManyField(Profile, related_name="roles",
            blank=True, null=True)
    modified = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now_add=True)

Поэтому всякий раз, когда создается новое событие, вместе с ним создается множество ролей. В модели Invite, как я могу показать только роли, связанные с событием, которое я выбрал в форме изменения в Django Admin, вместо того, чтобы показывать все записи в модели ролей?

Ответ 1

Вы хотите динамически фильтровать выбор roles choices, поэтому вам понадобится ajax для выполнения этой задачи.

Здесь вы можете сделать эту работу.

1: OnChange event отправьте event_id в свой пользовательский view через ajax.

2: Из roles модели filter на основе event_id, полученной из запроса ajax, и отфильтруйте roles на serializing в JSON,

3: Очистите существующий roles и заново обработайте с помощью анализа JSON.

Например: Это пример jquery getJSON

javascript:

$("#event").change(function (){         
 var event_id = $(this).val();              
    $.getJSON("/my-app/my-roles-filter-view/"+ event_id +"/",function(data){
        var roles_dd = $("#roles");
        $('#event >option').remove();
        $.each(data, function(index,value) {
        roles_dd.append($("<option />").val(value).text(value));
    });                 
})(django.jquery);

URL,

('^/my-app/my-roles-filter-view/(?P<event_id>\d+)/$','my_view'),

вид:

def my_view(request,event_id):
    qs = Role.objects.filter(event=event_id).values_list('id')
    return HttpResponse(simplejson.dumps(qs),mimetype='application/javascript')

В этом примере с помощью jquery вы можете использовать любой тип ajax и достичь этого.

Ответ 2

Вероятно, вы хотите что-то вроде:

class InviteAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        self.instance = obj # Capture instance before the form gets generated   
        return super(InviteAdmin, self).get_form(request, obj=obj, **kwargs)

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
        if db_field.name == 'role' and self.instance:
            # restrict role queryset to those related to this instance:         
            kwargs['queryset'] = self.instance.event.roles.all()
        return super(InviteAdmin, self).formfield_for_manytomany(
            db_field, request=request, **kwargs)

Документация Django для formfield_for_manytomany

Ответ 3

Вам необходимо предоставить собственный метод formfield_for_foreignkey в вашем классе администратора для модели.

В этом примере (из документации, которую я связал), вы должны начать:

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "car":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

Ответ 4

Я считаю, что есть два способа решить это:

  • ajax метод, описанный @Pannu

  • метод non-ajax, который может быть достигнут путем перемещения поля event вне формы изменения (что означает, что будет другая форма для изменения event) и фильтрации roles на основе текущего event, Недавно мне пришлось решить аналогичную проблему с ограничением доступных опций на основе принадлежности объекта конкретному сайту. Вот описание и код, если вам интересно: http://source.mihelac.org/2011/09/8/django-sites-ext/