получение родительского объекта в 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