получение родительского объекта в Django Admin Inline
Основной текст заметки
первый способ
самый красивый способ - это из get_formset в который передается родительский объект
def get_formset(self, request, obj=None, **kwargs):
# можно просто сохранить
self.instance = obj
# а можно подменить обработчик 'formfield_callback', добавляя в его вызов параметр obj
kwargs['formfield_callback'] = partial(self.formfield_for_dbfield, request=request, obj=obj)
return super(FosterParentsInlineAdmin, self).get_formset(request, obj, **kwargs)
def formfield_for_dbfield(self, db_field, **kwargs):
print('self.instance', self.instance)
#теперь можно получить объект так
#запоминание кажется более универсальным
form_obj = self.instance
# или так
form_obj = kwargs.pop('obj', None)
formfield = super(FosterParentsInlineAdmin, self).formfield_for_dbfield(db_field, **kwargs)
# и использовать его "по назначению"
if db_field.name == "parent" and form_obj:
formfield.queryset = form_obj.possible_parents_qs()
return formfield
второй способ который я нашел - это парсить запрос
def get_parent_object_id_from_request(self, request):
"""это функция которая вытаскивает (и кеширует) id объекта"""
if self.parent_object_id:
return self.parent_object_id
resolved = resolve(request.path_info)
if resolved:
self.parent_object_id = resolved.kwargs.get('object_id')
return self.parent_object_id
return None
def get_parent_object_from_request(self, request):
"""это функция которая вытаскивает (и кеширует) уже сам объект"""
if self.parent_object:
return self.parent_object
self.get_parent_object_id_from_request(request)
if self.parent_object_id:
self.parent_object = self.parent_model.objects.get(pk=self.parent_object_id)
return self.parent_object
return None
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "parent":
# вот тут я получаю id объекта который мне нужен
self.get_parent_object_id_from_request(request)
if self.parent_object_id:
kwargs["queryset"] = Category.objects.exclude(pk=self.parent_object_id)
return super(FosterParentsInlineAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Программный код
вот пример класса
class FosterParentsInlineAdmin(SortableStackedInline):
model = Category.foster_parents.through
fk_name = "child"
can_delete = True
extra = 1
formset = FosterParentsInlineFormSet
# def __init__(self, *args, **kwargs):
# super(FosterParentsInlineAdmin, self).__init__(*args, **kwargs)
# self.parent_object_id = None
# self.parent_object = None
#
# #
# def formfield_for_foreignkey(self, db_field, request, **kwargs):
# if db_field.name == "parent":
# self.get_parent_object_id_from_request(request)
# if self.parent_object_id:
# kwargs["queryset"] = Category.objects.exclude(pk=self.parent_object_id)
# return super(FosterParentsInlineAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
#
#
# def get_parent_object_id_from_request(self, request):
# if self.parent_object_id:
# return self.parent_object_id
# resolved = resolve(request.path_info)
# if resolved:
# self.parent_object_id = resolved.kwargs.get('object_id')
# return self.parent_object_id
# return None
#
#
# def get_parent_object_from_request(self, request):
# if self.parent_object:
# return self.parent_object
# self.get_parent_object_id_from_request(request)
# if self.parent_object_id:
# self.parent_object = self.parent_model.objects.get(pk=self.parent_object_id)
# return self.parent_object
# return None
def get_formset(self, request, obj=None, **kwargs):
print('get_formset!!!!')
self.instance = obj
kwargs['formfield_callback'] = partial(self.formfield_for_dbfield, request=request, obj=obj)
return super(FosterParentsInlineAdmin, self).get_formset(request, obj, **kwargs)
def formfield_for_dbfield(self, db_field, **kwargs):
print('---- formfield_for_dbfield db_field=',db_field)
form_obj = kwargs.pop('obj', None)
print('form_obj_v1',form_obj)
print('form_obj_v2', self.instance)
formfield = super(FosterParentsInlineAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == "parent" and form_obj:
formfield.queryset = form_obj.possible_parents_qs()
return formfield
def formfield_for_foreignkey(self, db_field, request, **kwargs):
print('---- formfield_for_foreignkey db_field=',db_field)
form_obj = kwargs.pop('obj', None)
print('form_obj_v1',form_obj)
print('form_obj_v2', self.instance)
return super(FosterParentsInlineAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
#формирует такой результат
formfield_for_foreignkey db_field store.Category.parent
get_field_queryset db_field store.Category.parent
get_formset!!!!
get_formset!!!!
---- formfield_for_dbfield db_field= store.FosterParentPivot.id
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_dbfield db_field= store.FosterParentPivot.child
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_foreignkey db_field= store.FosterParentPivot.child
form_obj_v1 None
form_obj_v2 третья
---- formfield_for_dbfield db_field= store.FosterParentPivot.parent
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_foreignkey db_field= store.FosterParentPivot.parent
form_obj_v1 None
form_obj_v2 третья
---- formfield_for_dbfield db_field= store.FosterParentPivot.child
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_foreignkey db_field= store.FosterParentPivot.child
form_obj_v1 None
form_obj_v2 третья
---- formfield_for_dbfield db_field= store.FosterParentPivot.parent
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_foreignkey db_field= store.FosterParentPivot.parent
form_obj_v1 None
form_obj_v2 третья
FosterParentsInlineFormSet.instance третья
get_formset!!!!
---- formfield_for_dbfield db_field= store.FosterParentPivot.id
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_dbfield db_field= store.FosterParentPivot.child
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_foreignkey db_field= store.FosterParentPivot.child
form_obj_v1 None
form_obj_v2 третья
---- formfield_for_dbfield db_field= store.FosterParentPivot.parent
form_obj_v1 третья
form_obj_v2 третья
---- formfield_for_foreignkey db_field= store.FosterParentPivot.parent
form_obj_v1 None
form_obj_v2 третья
Заметка написана: 27.05.2020
Теги заметки: Django, Django admin