Преобразование SQL в то, что может использовать Django
Я работаю над преобразованием относительно сложного SQL в то, с чем может играть Django. Я стараюсь не использовать только необработанный SQL, поскольку я думаю, что игра со стандартным набором инструментов Django поможет мне узнать больше о Django.
Мне уже удалось разбить части sql на куски, и я решаю их по частям, чтобы сделать все немного проще.
Вот SQL, о котором идет речь:
SELECT i.year, i.brand, i.desc, i.colour, i.size, i.mpn, i.url,
COALESCE(DATE_FORMAT(i_eta.eta, '%M %Y'),'Unknown')
as eta
FROM i
JOIN i_eta ON i_eta.mpn = i.mpn
WHERE category LIKE 'kids'
ORDER BY i.brand, i.desc, i.colour, FIELD(size, 'xxl','xl','l','ml','m','s','xs','xxs') DESC, size+0, size
Вот что у меня есть (пытаюсь преобразовать строку за строкой):
(grabbed automatically when performing filters)
(have to figure out django doc on coalesce for syntax)
db alias haven't been able to find yet - it is crucial since there is a db view that requires it
already included in the original q
.select_related?
.filter(category="kids")
.objects.order_by('brand','desc','colour') - don't know how to deal with SQL FIELDS
Любой совет будет оценен по достоинству!
Вот как я бы это структурировал.
Во-первых, я предполагаю, что ваши модели для i и i_eta выглядят примерно так:
class I(models.Model):
mpn = models.CharField(max_length=30, primary_key=True)
year = models.CharField(max_length=30)
brand = models.CharField(max_length=30)
desc = models.CharField(max_length=100)
colour = models.CharField(max_length=30)
size = models.CharField(max_length=3)
class IEta(models.Model):
i = models.ForeignKey(I, on_delete=models.CASCADE)
eta = models.DateField()
Общие мысли:
Для написания coalesce в Django: Я бы не стал заменять нули на "Unknown" в ORM. Это проблема презентационного уровня: она должна решаться в шаблоне.
.Для форматирования даты вы можете сделать форматирование даты в Python.
Не уверен, что такое псевдоним БД.
Для использования нескольких таблиц вместе, вы можете использовать либо select_related(), prefetch_related(), либо ничего не делать.
- select_related() будет выполнять объединение.
- prefect_related() получит идентификаторы внешних ключей из первого набора запросов, затем создаст запрос типа
SELECT * FROM table WHERE id in (12, 13, 14)
. - Ничего не делая, запрос будет работать автоматически, но имеет недостаток в виде проблемы SELECT N+1.
Я обычно предпочитаю prefetch_related().
Для настройки порядка сортировки поля size у вас есть три варианта. Я предпочитаю вариант 1, но подойдет любой из трех.
- Денормализуйте критерии сортировки. Добавьте новое поле с именем size_numeric. Переопределите метод save(), чтобы заполнять это поле при сохранении новых экземпляров, присваивая xxl значение 1, xl значение 2 и т.д. .
- Сортировка в Python. По сути, вы используете встроенные методы сортировки Python для выполнения сортировки, а не сортируете в базе данных. Это не очень хорошо работает, если у вас тысячи результатов.
- Вызовите функцию MySQL. По сути, используя annotate(), вы добавляете вывод функции в набор запросов. order_by() может сортировать по этой функции. .