Вы можете использовать атрибут column_property
, чтобы сделать model
«локальным» для Smart
, за счет наличия коррелированного подзапроса:
class Drives(Base):
__tablename__ = 'drives'
id = Column(Integer, primary_key=True)
model = Column(String)
class Smart(Base):
__tablename__ = 'smart'
drive = Column(Integer, ForeignKey(Drives.id), primary_key=True)
ts = Column(DateTime, primary_key=True)
value = Column(Integer)
drives = relationship(Drives)
model = column_property(select([Drives.model]).where(Drives.id == drive))
__mapper_args__ = {'polymorphic_on': model}
class ModelASmart(Smart):
__mapper_args__ = {'polymorphic_identity': 'ModelA'}
@hybrid_property
def actual_value(self):
return self.value * 2
class ModelBSmart(Smart):
__mapper_args__ = {'polymorphic_identity': 'ModelB'}
@hybrid_property
def actual_value(self):
return self.value * 3
Свойство столбца всегда будет включено в ваши запросы, что означает, что коррелированный подзапрос, вероятно, будет определять производительность запроса.
В SQLAlchemy есть и другие способы введения атрибутов через отношения, такие как прокси-серверы ассоциации и гибридные свойства, но они не могут использоваться в качестве polymorphic_on
дискриминатора. Еще одной, немного более экзотической, возможностью будет отобразить Smart
поверх соединения между таблицами smart
и drives
.
Другой вариант - отказаться от использования наследования и использовать вместо него простое гибридное свойство в Smart
:
class Drives(Base):
__tablename__ = 'drives'
id = Column(Integer, primary_key=True)
model = Column(String)
class Smart(Base):
__tablename__ = 'smart'
drive = Column(Integer, ForeignKey(Drives.id), primary_key=True)
ts = Column(DateTime, primary_key=True)
value = Column(Integer)
drives = relationship(Drives)
_model_coeff = {
'ModelA': 2,
'ModelB': 3,
}
@hybrid_property
def actual_value(self):
return self.value * self._model_coeff[self.drives.model]
@actual_value.expression
def actual_value(cls):
return cls.value * case(
cls._model_coeff,
value=select([Drives.model]).
where(Drives.id == cls.drive).
as_scalar())
При этом используется «сокращенный» формат case()
для сопоставления поиска dict
с выражением SQL CASE
. Запрос, такой как:
session.query(Smart, Smart.actual_value)
будет использовать коррелированный подзапрос для выбора между коэффициентами, но есть и другой вариант с использованием активной загрузки:
session.query(Smart).options(joinedload(Smart.drives, innerjoin=True))
Таким образом, связанный Drives
] экземпляр загружается в тот же запрос, поэтому гибридному свойству не нужно выполнять выборку при доступе к экземпляру:
# `s` is an instance from the previous eager loading query. This access
# will not fire additional queries.
s.actual_value
Вообще-то, по моему опыту, вы хотите избежать любого Javascript на своей странице, который вы можете. Под этим я подразумеваю, что если вы можете сделать это на стороне сервера, а не с помощью Javascript, то вам следует. Ваша страница будет загружаться быстрее, и вы просто получите лучший пользовательский опыт.
Иногда это может потребовать больше усилий, особенно если тот же вызов AJAX при загрузке используется во время страницы в более поздние моменты. Вы можете дублировать код, делая это на стороне сервера. Таким образом, существует компромисс между производительностью и объемом кода, который вы хотите написать.
Другой аспект этого заключается в том, что Javascript иногда используется для защиты от ботов, скребков, вредоносных программ (таких как keyniffers и т. Д.) И т. Д. Как для вашей безопасности, так и для безопасности. что на сайте. Это может означать, например, загрузку элементов страницы с помощью Javascript просто потому, что это усложняет взлом или очистку.
Я бы написал на стороне начальной страницы сервера, чтобы включить этот первый потенциальный вызов AJAX, а затем использовал бы реальный AJAX для чего-либо после этого. Вы хотите проделать больше работы на своем конце, чтобы сделать его быстрее для конечного пользователя.
Я видел сайт, который использует AJAX для основного контента. Когда сторона находится под нагрузкой, она отобразит панель навигации, и вы не увидите ничего еще 5 секунд, потому что она загружается вызовом AJAX, и вы потеряли свое место в очереди. Это чертовски раздражает.
Я использую AJAX под нагрузкой, главным образом, чтобы избежать дублирования усилий и сделать вещи простыми - если мне все равно придется выполнять рендеринг на стороне клиента для обновлений, лучше использовать тот же код для начального рендеринга.
Наличие всего, что было создано с помощью javascript, имеет значение для поиска и т. Д., Но если вы знаете об этом при разработке страницы, это не слишком большая проблема.
Как правило, вы правы, если вы изначально перетягиваете страницу с сервера, зачем делать еще одну поездку, чтобы получить больше данных? Но если данные большие, то вы можете также загрузить страницу, чтобы конечные пользователи могли что-то увидеть, а затем извлечь данные.
Данные могут быть извлечены с помощью Ajax, потому что подобный метод поиска данных часто используется на странице. Зачем писать отдельный механизм извлечения данных для начальной загрузки, если вы все равно собираетесь выполнять несколько Ajax-загрузок.
Кроме того, всегда помните, что демонстрации - это просто демонстрации. Парни из Nerd Dinner, вероятно, были более заинтересованы в том, чтобы показать, как использовать AJAX с MVC, чем о других приоритетах.
В любом случае, хороший улов.
Я согласен с Адамом. Если у вас есть большая сложная страница, для отображения которой вашему серверу может потребоваться некоторое время, но на ней есть только несколько бит динамического содержимого, вы можете получить большие преимущества в производительности за счет активного кэширования HTML и загрузки динамического содержимого с помощью Ajax.
В качестве примера представьте главную страницу сайта, на которой должно отображаться имя пользователя в углу. Все, кто посетит ваш сайт, попадут на эту страницу, поэтому чем больше вы сможете кэшировать для HTML, тем лучше. Заполнив имя пользователя с помощью Ajax, вы можете обслуживать одну и ту же кэшируемую версию HTML для всех и отдельно обслуживать гораздо меньший динамический контент.
Кэшируемость становится еще более важной, если вы работаете с не очень быстрым сервером технология - в случае необходимости - Ruby on Rails. Вы можете получить хороший прирост скорости на стороне сервера, обслуживая страницы через прокси-сервер, такой как Varnish или Squid, который хранит кешированную копию каждой обслуживаемой страницы. Последующие запросы того же ресурса будут обслуживаться из кеша прокси, а не из кода вашего сервера, пока кеш не станет устаревшим.
Вызов AJAX при загрузке страницы должен сохранить отделение презентации от контента / данных.
Презентация (страница HTML) может быть кэширована браузером, а вызов AJAX извлекает данные только для обновления пользовательского интерфейса.
Это может привести к очень чистому разделению, а также к некоторым преимуществам в производительности. На самом деле вы передаете меньше информации по сети, поскольку не передаете суп HTML-тега - просто в любом представлении, в котором хранятся ваши данные.
Просто причина, по которой я мог это видеть:
Выполнение вызова AJAX для загрузки исходных данных может служить способом проверки того, что Javascript включен и что последующие вызовы AJAX должно сработать. В противном случае может случиться так, что первый вызов сервера, выполненный клиентом с использованием JavaScript, не будет работать, и пользователь может быть разочарован тем, почему это не работает, не понимая, что причина в его настройках безопасности.
Я не понимаю, как здесь размер запроса / ответа. Использование AJAX или нет - больше вопрос юзабилити, и одним из факторов здесь является время рендеринга начальной страницы. Пользователи не хотят ждать. Если вам требуется всего 2 секунды для вычисления элемента страницы на стороне сервера, вам определенно следует подумать о том, чтобы сначала отправить страницу без этого элемента, а затем получить элемент через ajax. Даже если этот элемент страницы имеет только пару байтов.
Основной проблемой является не размер, а дополнительная задержка запроса / блокировка доступных слотов параллельного запроса.
If the user clicks back / forward, the server will not get called again since its pulling the content out of cache. However, with an ajax call on client side pageload, the server will always get called.
Лучшая причина для этого - иметь единый источник для контента: вместо того, чтобы получать первый экземпляр, встроенный в страницу, и обновленные экземпляры, поступающие из Ajax, теперь каждый экземпляр поступает из Ajax.
Другими словами: делать по-своему - двойная работа,
Против Ajax при загрузке страницы
Для Ajax при загрузке страницы
Многие из них также просто зависит от того, на каком участке ваша постройка. Вы должны быть осторожны с большими сайтами, чтобы не полагаться на тонны маленьких вызовов Ajax прямо при загрузке страницы.
Наилучшим решением, по-видимому, является вызов функции Ajax на стороне сервера и загрузка содержимого json при загрузке страницы. Это обеспечивает согласованность действий и позволяет избежать лишних подключений при запуске.