Похоже, все ваши виджеты делят обработчик событий. Этот отрывок из Tkinter 8.4 Reference Джона У. Шипмана - NM Tech может помочь.
30.7. Дополнительный аргумент trick
Иногда вам нужно передать другие аргументы обработчику, кроме события.
Вот пример. Предположим, что ваше приложение имеет массив из десяти контрольных кнопок, чьи виджеты хранятся в списке
self.cbList
, индексируются номером контрольной кнопки вrange(10)
.Предположим, что вы хотите написать один обработчик с именем
.__cbHandler
для событийво всех десяти из этих контрольных кнопок. Обработчик может получить фактический виджет
Checkbutton
, который вызвал его, обратившись к атрибуту.widget
объектаEvent
, который передается, но как он узнает, что индекс контрольной кнопки вself.cbList
?Было бы неплохо написать наш обработчик с дополнительным аргументом для номера контрольной кнопки, что-то вроде этого:
def __cbHandler ( self, event, cbNumber ):
Но обработчики событий передаются только одному аргументу - событию. Таким образом, мы не можем использовать вышеприведенную функцию из-за несоответствия количества аргументов.
К счастью, способность Python предоставлять значения по умолчанию для аргументов функции дает нам выход. Посмотрите на этот код:
def __createWidgets ( self ): ? self.cbList = [] # Create the checkbutton list for i in range(10): cb = Checkbutton ( self, ? ) self.cbList.append ( cb ) cb.grid( row=1, column=i ) def handler ( event, self=self, i=i ): # [1] return self.__cbHandler ( event, i ) cb.bind ( "
", handler ) ? def __cbHandler ( self, event, cbNumber ): ?
#
[1] Эти строки определяют новую функциюhandler
, которая ожидает три аргумента. Первый аргумент - это объектEvent
, переданный всем обработчикам событий, а второй и третий аргументы будут установлены в их значения по умолчанию - дополнительные аргументы, которые нам нужно передать.Этот метод может быть расширен для подачи каких-либо дополнительных аргументов обработчикам.
blockquote>Несколько более краткий способ сделать это, поскольку Брайан Оукли делает для второй кнопки в свой ответ , является для определения каждой функции обработчика в строке с помощью лямбда, т. е.
def __createWidgets ( self ): ? self.cbList = [] # Create the checkbutton list for i in range(10): cb = Checkbutton ( self, ? ) self.cbList.append ( cb ) cb.grid( row=1, column=i ) cb.bind ( "
", lambda event, self=self, i=i: self.__cbHandler( event, i ) ) ? def __cbHandler ( self, event, cbNumber ): ?
Похоже, ваша ошибка возникла из-за того, что вы не указали basename
для своего маршрута в /app/really_simple_contact_management/urls.py
:
router.register(r'people', PersonViewSet)
Из документов :
< blockquote>basename - База для использования в именах URL, которые создаются. Если не задано, базовое имя будет автоматически сгенерировано на основе атрибута набора запросов в наборе, если таковое имеется. Обратите внимание, что если набор представлений не включает атрибут набора запросов, вы должны установить базовое имя при регистрации набора.
blockquote>Замените строку выше на:
router.register(r'people', PersonViewSet, base_name='people',)
Укажите значимую строку как base_name
в соответствии с вашими предпочтениями, и ошибка должна исчезнуть.
Вы вручную создаете и возвращаете set
, но функция get_queryset
ожидала фактический Django QuerySet .
Вы можете переписать свою функцию, используя оператор __in
:
def get_queryset(self):
user = self.request.user
allowed_lists = get_objects_for_user(user, ('view_list'), klass=List)
return Person.objects.filter(member__in=allowed_lists)