Pull to refresh
38
0.1
Максим @danilovmy

Программист разработчик

Send message
«Если get возвращает миллион записей...» — get возвращает один объект или ошибки. В процессе работы GET может создать много объектов на основе записей, возвращенных из базы.

Эта логическая ошибка в стандартном методе get заключается в том, что на 9 строке метода создаются объекты, которые, если их можно было создать больше одного — создаваться не должны были в принципе. А они создаются, и только потом проверяется их количество.

Кстати, когда выпал MultipleObjectsReturned, на обработке ошибки воспользоваться этими УЖЕ созданными «MultipleObjects» нельзя.
Противоречие в том, что моя фраза «В итоге вы могли получить несколько миллионов объектов в памяти, только для того, чтобы узнать, что найден более, чем 1 объект.» не говорит, что результатом работы метода GET будет возврат двух и более объектов.

однако именно она была приведена с комментарием «вот же», как пример того, что результатом работы метода GET будет возврат более одного объекта.
Речь идет о методе GET в родном коде django (django/db/models/query.py). Я описал как он работает:
Объекты сохраняются в "_result_cache".
Если обьект один — Get вернет ссылку на первый и единственный объект в "_result_cache"
GET выдаст ошибку «DoesNotExist» если _result_cache пустой
GET вернет MultipleObjectsReturned, при этом "_result_cache" будет заполнен несколькими объектами и их количество не учитывается.
_result_cache хранится в памяти, методом GET не возвращается.
метод get возвращал и возвращает только один объект или выдает ошибки. Ни в коде, ни в моем тексте я не вижу упоминаний что get по окончанию возвращает что-то другое.

прошу указать: где в коде или тексте статьи ошибка, подразумевающая, что результатом работы метода GET будет возврат двух и более объектов.
Пробовал. Десять открытых тикетов на сайте Джанго проекта и один несостоявшийся пулл реквест про конвертацию флоат/децимал- писал в предыдущей статье. В итоге плюнул, правим в нашем проекте под себя.
По логике, данная функция должна инициировать и возвращать только один объект, и делать это только в том случае, если объект один.

В реальной Django это невозможно сделать за один запрос. Потому текущая логика метода такова:
  • Проинициализировать объекты данными из запроса, будет проинициализировано столько объектов, сколько возвращено строк,
  • Объекты сохраняются в "_result_cache".
  • Если обьект один — Get вернет ссылку на первый и единственный объект в "_result_cache"
  • GET выдаст ошибку «DoesNotExist» если _result_cache пустой
  • GET вернет MultipleObjectsReturned, при этом "_result_cache" будет заполнен несколькими объектами и их количество не учитывается.


В Django 3 появилось ограничение в 25 строк, это значит, что в sql запроса есть «LIMIT». Во всех предыдущих версиях этого ограничения не было вообще, и мы поставили у себя в проекте ограничение на количество возвращенных строк до 2х.
В этом случае будут проинициированы максимум два обьекта. После чего Get выдаст ошибки, если получен иной результат, чем один объект.

Ограничение на 2 объекта вместо 25 я предлагаю и для новой Django.
Пробовал. Десять открытых тикетов на сайте Джанго проекта и один несостоявшийся пулл реквест про конвертацию флоат/децимал- писал в предыдущей статье. В итоге плюнул, правим в нашем проекте под себя.
Если судить по тому, что ограничение на количество получаемых объектов методом get уже попало в официальный релиз Django 3, то получается, что я не один такой сказочный долбо§б.

Я уже в статье отметил, что считаю, что в этой функции ошибка. Ошибка в логике: функция должна получать только один объект, если он есть. Не два, не 25, и не два миллиона. Жаль только, что мой манкипатчинг (смешное слово) не исправляет эту ошибку а только уменьшает количество получаемых объектов.

Разбит на несколько четвертей это как?

не там нажал ответ. фраза stilet69 была «Например понравился Новый берег марки Сира»

Предположу, что это привозной Шираз разлитый по бутылкам.

Как знать что принимает и возращает эта функция?

В приведенном мною моем решении — никак. Полагаю, что для этой функции будет достаточно методов самодокументации с говорящими именами и можно добавить docstring. Вариантов много, ADR, предлагайте свои.

return response.json()['url']

Конечно же как и url так и ответы от разных сервисов, скорее всего, отличаются. И перенастройка только URL может привести к ошибке KeyError.

Как логично заметил js605451 и позже еще и я отметил, в исходной функции много что прибито гвоздями, в том числе и ключ значения в ответе. Думаю, благодаря комментариям, автор статьи увидел это более четко.

Предположу, что понравится доклад и наработки про разделение бизнес логики на апрельском Джанго конф 2019. В моей статье на Хабре, ссылка есть, в третий день конференции.

Я не принимаю решение. Это код из статьи. API Key передается при инициализации класса и Я даже не знаю что это такое и откуда. А вот то, что ссылка захардкожена в коде функции, скорее всего недоработка. Как собственно и метод Post и заголовки и класс респонса. И ключ по которому получаем результат.

Раз так много заложено на стилях, может попробовать вариант исключительно через CSS с анимацией и потом доработать скриптом для управления? у нас так реализованы бэкграунд слайдеры.
Ужасно. Ужасно, насколько можно не понимать любимый мною и элегантный Python. Еще хуже только неумение читать документацию.

Начну с вопроса джангистам. Часто ли вы пишете вот эти две строчки?
import django; django.setup()

Ответ джангиста: Джангисты, обычно, не пишут эти строки. Они изначально работают с Django. Скорее это вопрос к Python-разработчикам, кто хочет использовать объекты Django «Stanalone»
С этого нужно начать файл, если вы хотите поработать с объектами django, не запуская сам вебсервер Django. Я постоянно пишу эти две строчки.

Нет. Не каждый. Более того, это должно быть написано только один раз в проекте согласно документации.

Вероятно автор ооочень любит что-то писать многократно, и подзабыл правило DRY: Если хотя бы две повторяющихся строчки можно превратить в одну, то надо так и сделать:
Можно сделать хелпер i_love_import_django_everywhere.py.
import django as _dj; dj.setup(); Django=_dj 

и импортировать везде в файлах:
from i_love_import_django_everywhere.py import Django


Импорт константы. Вместо привычного места хранения констант в Settings (или где вы там организовали хранилище настроек), автор предлагает захардкодить значение настройки в коде.

Представляю: приходит новый сотрудник, изучает структуру, ага питон код, ага объекты из Django, ага для изменения поведения Объекта из Django надо поменять настройки в Django. Меняет… и ничего не происходит.
Потому, как предыдущий разработчик узнал про то, как плохо делать импорт зависимостей. И про паттерны в ООП узнал.
И, похоже, забыл узнать про Инкапсуляцию, которая предлагает убрать все изменяемые данные туда, где они реально меняются. в Django для этого есть Settings.

Автор отмечает, что история с зависимостью от Django — это пример проблемы, с которой он сталкивается каждый день.
Однако: Если зависимость от Django ежедневная, то, либо стоит просто начать писать под Django, либо стоит отказаться от Django,… либо это просто не проблема.

На выдуманную проблему «сломанного интерфейса» прекрасно ответил kommie2050
def shorten_link(self, *args, **kwargs)
— Это действительно «more pythonic».
Я предлагаю дополнить это решение так:

def shorten_link(self, *args, **kwargs):
    response = requests.post(
        url=settings.SHORTER_URL,
        headers={'Authorization': self.api_key},
        json= kwargs,
    )
    return response.json()['url']

Теперь shorten_link готов принимать в качестве Kwargs любое количество управляющих переменных.
А вместо захардкоренного в коде URL я предлагаю вынести это значение в хранилище настроек. Адреса сервисов, знаете ли, иногда меняются…

Все что предложено автором ниже — это кропотливо скопированный код из книги по паттернам OOP для Java. Очень похоже на стиль из серии учебников Head First.

Только автор забыл, что речь идет о Python, где тотальное следование OOP бессмысленно.
Например, есть шикарный доклад "паттерны OOP в Python? Вам это не нужно"

В общем, могу порекомендовать автору статьи поработать с наставником, консультантом, тем, кто понимает Python и у кого хватит сил объяснить, что Python это не Java.
Наш высоко нагруженный мультиязычный проект написан на Джанго. Потому мониторю появляющиеся решения. Посмотрел две презентации по Джанго, стало жалко ребят:
«Поиск и устранение узких мест при масштабировании» рассказ о том, как разработчик боролся со своим собственным кодом: видя ошибку архитектуры они продолжают заниматься оптимизацией старого кода, хотя видно же, что для масштабирования надо переделывать архитектуру. Не, вместо этого ребята продолжают скакать на мертвой лошади на устаревшей архитектуре приложения , просто они решили стегать плеткой чаще.
Логично, когда хотим убыстрить, перестаем подгружать ненужные поля… стоп… а зачем у вас вообще ненужные поля в модели? Да и сама структура 4 таблиц выглядит странно. Непонятно, зачем делать objects.GET(только id). разве values_list(pk, flat true) не сделает это быстрее? Кстати, надо проверить на миллионе записей. Ребятам успехов.

Мультиязычность это больное место в Джанго, как и многих других систем. Знаю не по наслышке, несколько лет был тех директором бюро мультиязычной поддержки, занимались проблемами мультиязычности на веб сайтах.

Сейчас у нас в проекте, что я упомянул выше, много самостоятельных решений по вопросам мультиязычности, потому что родная мультиязычная поддержка очень плохо реализована на Джанго. Из переводных моделей парлер, хвад (лучше парлера) и модель транслейшн. Из перевода интерфейсов — розетта.
По докладу вижу что люди делают что то не то: у них 32 языка и нет никакой автоматизации и проверки перевода??? Менеджер должен заходить в папку и править файл??? Да менеджер переводчик даже знать не должен где эти файлы. Та же джанго розетта ужасна но позволяет избежать проблем «не поставил запятую». У нас стояла софтина, жаль только в локальной сети работала, для всех переводчиков, где ядро переводов потихоньку заполнялось, и после, попадающиеся похожие переводы не надо было переводить. И точно никакой жести с json или текcтовыми файлами.

Если кто еще знает про мультиязычность в джанго, подскажите. Есто что то еще похожее на hvad, только для новой джанго?
werevolff спасибо за статью, воткнулся сейчас в эту проблему с документацией, в итоге переделал с viewset на views, в итоге оказалось кода меньше.

По поводу Django-писания, матчасть стоит подтянуть. Я, например, писал об этом в своей статье:
Django-разработчик, помни: все что ты делаешь — это настройка WSGI-приложения.
Посмотри документацию о превращении входящего запроса на сервер в исходящий ответ.
Сomtypes работает только в виндовс это аналог com+ addins в виндовом оффисе.
Сохранение в ворде в пдф через макрос делается в одну команду:

ActiveDocument.ExportAsFixedFormat OutputFileName:= _
        filename, ExportFormat:=wdExportFormatPDF, _
        OpenAfterExport:=False, OptimizeFor:=wdExportOptimizeForPrint, Range:= _
        wdExportAllDocument, BitmapMissingFonts:= True


Если я правильно помню, то это сработает для любой ос.

zoldaten,
если ты делаешь
word = comtypes.client.CreateObject('Word.Application')

то DocxTemplate уже ненужен, ты же фактически ворд запустил в питоне. работай тогда уже с настоящими командами ворда, как я писал выше:

wdFormatPDF = 17
in_file = os.path.abspath ("final.docx")
out_file = os.path.abspath("final.pdf")
word = comtypes.client.CreateObject('Word.Application')
doc = word.Documents.Open(in_file)
doc.Variables.Item("EMITENT") = "Емитент"
doc.Variables.Item("ADDRESS1") = "Адрес"
doc.Variables.Item("DIRECTOR") = "Директор"
doc.Fields.Update
doc.SaveAs(out_file, FileFormat=wdFormatPDF)


Я думал это твоя статья: habr.com/ru/post/455808, обе статьи — эта и вторая появились в одно время.

Information

Rating
3,294-th
Location
Zams, Tirol, Австрия
Date of birth
Registered
Activity

Specialization

Backend Developer, Fullstack Developer
Lead
From 8,000 €
Python
Django
Ajax
OOP
Design patterns
Vue.js
JavaScript
HTML
CSS