У меня есть модель для Заказов в приложении для веб-магазина с автоматически увеличивающимся первичным ключом и внешним ключом для себя, так как заказы можно разделить на несколько заказов, но связь с исходным заказом должна поддерживаться.
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/None), никакие заказы не должны отображаться. Для заказов, которые были разделены, это должно отображать только один родительский порядок.
Здесь доступен довольно новый метод 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=?????)
Я не нашел рабочего места для замены????? со ссылкой на "текущий" экземпляр заказа, и я выкопал довольно глубоко. self
внутри formfield_for_foreignkey
относится к экземпляру ModelAdmin, и хотя у него есть атрибут model
, это не экземпляр модели заказа (это ссылка ModelBase; self.model() возвращает экземпляр, но его порядковый номер - None).
Одним из решений может быть вытащить номер заказа из request.path(/admin/orders/order/11234/), но это действительно уродливо. Мне очень жаль, что есть лучший способ.