У меня есть модель для заказов в приложении интернет-магазина с автоматически возрастающим первичным ключом и внешним ключом к себе, поскольку заказы можно разбить на несколько заказов, но необходимо сохранить связь с исходным заказом.
class Order(models.Model):
ordernumber = models.AutoField(primary_key=True)
parent_order = models.ForeignKey('self', null=True, blank=True, related_name='child_orders')
# .. other fields not relevant here
Я зарегистрировал класс OrderAdmin для сайта администратора. Для подробного просмотра я включил parent_order
в атрибут fieldsets
. Конечно, по умолчанию это перечисляет все заказы в окне выбора, но это не желаемое поведение. Вместо этого, для заказов, у которых нет родительского заказа (то есть, которые не были отделены от другого заказа; parent_order
равен NULL / Нет), никакие заказы не должны отображаться. Для заказов, которые были разделены, должен отображаться только родительский заказ.
Доступен довольно новый метод ModelAdmin, formfield_for_foreignkey
, который кажется идеальным для этого, поскольку набор запросов может быть отфильтрован внутри него. Представьте, что мы смотрим на подробный вид заказа # 11234, который был отделен от заказа # 11208. Код ниже
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'parent_order':
# kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=11234)
return db_field.formfield(**kwargs)
return super(OrderAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
Комментируемая строка работает при запуске в оболочке Python, возвращая набор запросов из одного элемента, содержащий заказ # 11208 для # 11234 и все другие заказы, которые могли быть от него отделены.
Конечно, мы не можем жестко закодировать там номер заказа. Нам нужна ссылка на поле ordernumber
экземпляра заказа, на странице подробностей которого мы просматриваем. Как это:
kwargs["queryset"] = Order.objects.filter(child_orders__ordernumber__exact=?????)
Я не нашел рабочего способа заменить ????? со ссылкой на «текущий» экземпляр Order, и я выкопал довольно глубоко. self
внутри formfield_for_foreignkey
относится к экземпляру ModelAdmin, и хотя у него есть атрибут model
, это не экземпляр модели заказа (это ссылка на ModelBase; self.model () возвращает экземпляр, но его порядковый номер равен None ).
Одним из решений может быть получение номера заказа из request.path (/ admin / orders / order / 11234 /), но это действительно ужасно. Я действительно хочу, чтобы был лучший способ.