Множество запросов 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/