LXF117:google
(викификация, оформление,) |
(Викификация, оформление) |
||
Строка 99: | Строка 99: | ||
Теперь можно добавить в CSS-файл какой-нибудь стиль – сделайте это сами. | Теперь можно добавить в CSS-файл какой-нибудь стиль – сделайте это сами. | ||
+ | |||
+ | ====Сохранение моделей==== | ||
+ | |||
+ | Масштабирование баз данных – сложная задача, но Google нашел несколько умных способов ее решения, применив новый подход к традиционным реляционным БД. | ||
+ | |||
+ | ''BigTable'' от Google – сердце системы хранения данных ''App Engine''. Это означает, что можно создавать приложения, способные масштабироваться до миллионов пользователей и страниц. ''BigTable'' – это распределенная система хранения, созданная для управления «петабайтами данных на тысячах стандартных серверов» (http://labs.google.com/papers/bigtable.html), но начать работать с ней в ''App Engine'' очень просто. Все начинается с моделей, создание которых требует несколько строчек кода. Модели в ''App Engine'' являются классами-расширениями '''db.Model'''. Их свойства аналогичны свойствам полей в таблицах обычных баз данных. Вот пример простой модели: | ||
+ | |||
+ | <source lang=python> | ||
+ | class MyNote(db.Model): | ||
+ | thenote = db.StringProperty(multiline=True) | ||
+ | date = db.DateTimeProperty(auto_now_add=True) | ||
+ | </source> | ||
+ | |||
+ | В свойство '''date''' автоматически записывается текущее время благодаря методу '''auto_now_add''', свойство '''thenote''' – просто строка. Типы параметров включают логический ('''boolean'''), целые числа ('''integer'''), числа с плавающей точкой ('''float'''), двоичные данные ('''blob'''), почтовые сообщения ('''emails''') и другие. | ||
+ | |||
+ | Подготовка никакая не нужна – просто создайте экземпляр класса, установите его свойства и вызовите метод '''put()''': | ||
+ | |||
+ | <source lang=python> | ||
+ | note = MyNote() | ||
+ | note.thenote = ”Just a quick note” | ||
+ | note.put() | ||
+ | </source> | ||
+ | |||
+ | В нашем примере мы начнем с создания модели для хранения комментариев и назовем ее '''Comment''': | ||
+ | <source lang=python> | ||
+ | class Comment(db.Model): | ||
+ | content = db.StringProperty(multiline=True) | ||
+ | date = db.DateTimeProperty(auto_now_add=True) | ||
+ | author = db.UserProperty() | ||
+ | </source> | ||
+ | |||
+ | {{Врезка|Заголовок=Ведение журнала|Содержание=Сделайте ведение журнала своей привычкой – добавьте '''‘import logging’''' в начало приложения и записывайте сообщения в журнал: | ||
+ | |||
+ | logging.info(”Something’s happening...”) | ||
+ | |||
+ | Файлы журналов можно просмотреть через панель инструментов – зайдите в пункт Logs и вникните в каждую подробность.|Ширина=200px}} | ||
+ | |||
+ | Теперь добавим в приложение немного данных, просмотрим их и установим им несколько интересных свойств. Чтобы добавить несколько комментариев, нужно создать форму, сохранить данные и затем отобразить их. Начнем с добавления формы в файл '''index.html''': | ||
+ | <source lang=xml> | ||
+ | <form action=”/” method=”post” accept-charset=”utf-8”> | ||
+ | <input type=”hidden” name=”parent” value=”{{ comment.key }}” /> | ||
+ | <textarea name=”comment”></textarea> | ||
+ | <input type=”submit” value=”Add”></div> | ||
+ | </form> | ||
+ | </source> | ||
+ | |||
+ | Затем добавим метод '''post()''' в контроллер. | ||
+ | |||
+ | <source lang=python> | ||
+ | def post(self): | ||
+ | c = Comment() | ||
+ | c.content = self.request.get(‘comment’) | ||
+ | c.author = users.get_current_user() | ||
+ | c.put() | ||
+ | self.redirect(‘/’) | ||
+ | </source> | ||
+ | |||
+ | Для извлечения данных из хранилища используется ''GQL'', и по большей части он похож на ''SQL''. | ||
+ | Вам нужно заменить содержимое метода '''get()''' вызовом метода ''GQL'' класса '''Comment''', который | ||
+ | затем передать в шаблон: | ||
+ | <source lang=python> | ||
+ | comments = Comment.gql(“ORDER BY date DESC“) | ||
+ | template_vars = | ||
+ | { ‘comments’: comments | ||
+ | } | ||
+ | self.response.out.write(template.render(‘index.html’,template_vars)) | ||
+ | </source> | ||
+ | |||
+ | Наконец, можно пройтись по комментариям и отобразить их: | ||
+ | <source lang=xml> | ||
+ | {% for comment in comments %} | ||
+ | <p>{{ comment.content }}</p> | ||
+ | {% endfor %} | ||
+ | </source> | ||
+ | |||
+ | {{Врезка|Заголовок=Скорая помощь|Содержание=Через ''Google Data Services'' можно получить данные Google для своих приложений. Начните с установки модуля '''gdata''' в каталог вашего приложения по инструкциям | ||
+ | на http://code.google.com/appengine/docs/usinggdataservi-ces.html и затем импортируйте его командой ''import gdata''. | Ширина=200px}} | ||
+ | |||
+ | Для ясности и простоты добавления нового функционала переместите строку с обработкой комментариев в другой файл. Замените вторую строку из последнего примера на '''{ % include ‘comment.html’ %}''' | ||
+ | и создайте файл '''comment.html''' со следующим содержимым: | ||
+ | |||
+ | <source lang=xml> | ||
+ | <div class=“comment row1”> | ||
+ | <p><strong�Posted on | ||
+ | {{ comment.date }}</strong><br /> {{ comment.content }} </p> | ||
+ | </div> | ||
+ | </source> | ||
+ | |||
+ | ===Использование пользователей=== | ||
+ | |||
+ | ''App Engine'' позволяет аутентифицировать пользователей по существующим учетным записям Google, и вашим посетителям нет нужды регистрироваться заново ради очередного web-приложения. Для всего этого используется пакет '''users''': | ||
+ | |||
+ | <source lang=python> | ||
+ | from google.appengine.api import users | ||
+ | </source> | ||
+ | |||
+ | Теперь можно получить доступ к имени пользователя и его email-адресу с помощью функции '''users.get_current_user()'''. Если пользователь еще не вошел в систему, можно перенаправить его | ||
+ | на форму входа: | ||
+ | <source lang=python> | ||
+ | if users.get_current_user(): | ||
+ | user = get_current_user() | ||
+ | self.response.out.write(“You are logged in as: “ + user. nickname()) | ||
+ | else: self.redirect(users.create_login_url(“/home”)) | ||
+ | </source> | ||
+ | |||
+ | Параметр '''/home''' – это URL, на который вы направляете пользователя после входа в систему. | ||
+ | |||
+ | В приложении обработки комментариев можно заставить пользователей регистрироваться, прежде чем начинать что-либо писать; перенаправим их на страницу входа: | ||
+ | <source lang=python> | ||
+ | if users.get_current_user(): | ||
+ | comments = �omment.gql(“WHERE in_reply_to =:1 ORDER BY date DESC“, None) | ||
+ | template_vars = { | ||
+ | ‘comments’: comments | ||
+ | } | ||
+ | self.response.out.write(template.render(‘index.html’, template_vars)) | ||
+ | else: | ||
+ | message = (“<a href=’ %s’>Please login</a>.” %users. create_login_url(“/rels”)) | ||
+ | self.response.out.write(message) | ||
+ | </source> | ||
+ | |||
+ | Обновите приложение в браузере, чтобы убедиться, что аутентификация работает. | ||
+ | |||
+ | Теперь, когда пользователи вошли в систему, сохраняйте авторов всех комментариев, добавив следующую строку в метод '''post()''' перед командой '''c.put()''': | ||
+ | |||
+ | c.author = users.get_current_user() | ||
+ | |||
+ | Чтобы вывести имя и e-mail автора комментария, добавьте следующие строки в файл '''comment.html''': | ||
+ | |||
+ | <source lang=xml> | ||
+ | <p><b>Posted by: <b> | ||
+ | {% if comment.author.nickname %} | ||
+ | {{ comment.author.nickname }} ({{ comment.author.email }}) | ||
+ | {% else %} | ||
+ | Anonymous | ||
+ | {% endif %} | ||
+ | on {{ comment.date }} | ||
+ | </p> | ||
+ | </source> | ||
+ | |||
+ | ====Связанные сущности==== | ||
+ | |||
+ | Отношения между сущностями задаются внутри модели с помощью метода '''ReferenceProperty''', который ссылается на другую модель, или '''SelfReferenceProperty''', который ссылается на текущую. Связать одну модель с другой можно примерно так: | ||
+ | |||
+ | related_thing = db.ReferenceProperty(OtherThing) | ||
+ | |||
+ | Если вы хотите, чтобы пользователи могли отвечать на сообщения, оставленные на доске объявлений, у каждого комментария должен быть родитель '''_parent_''', которого мы назовем '''in_reply_to'''. Объявите это свойство, добавив в модель �omment следующую строку: | ||
+ | |||
+ | in_reply_to = db.SelfReferenceProperty() | ||
+ | |||
+ | Теперь можно добавить форму для каждого существующего комментария: | ||
+ | |||
+ | <source lang=xml> | ||
+ | <div> | ||
+ | <div id=“comment-{{ comment.key }}” style=“display:none;”> | ||
+ | <form action=“/rels” method=“post” acceptcharset=“utf-8”> | ||
+ | <input type=“hidden” name=“parent” value=”{{ comment.key }}” /> | ||
+ | <textarea name=“comment” rows=“7” cols=”30”></textarea> | ||
+ | <input type=“submit” value=“Add”> | ||
+ | </form> | ||
+ | </div> | ||
+ | <a href=“javascript:document.getElementById(‘comment-{{comment.key}}’).style.display=’block’;”>Add comment</a> | ||
+ | </div> | ||
+ | </source> | ||
+ | |||
+ | …а затем изменить метод '''post()''', чтобы сохранить его: | ||
+ | |||
+ | <source lang=python> | ||
+ | if self.request.get(‘parent’): | ||
+ | key_name = self.request.get(‘parent’) | ||
+ | p = db.get(db.Key(key_name)) | ||
+ | c.in_reply_to = p | ||
+ | else: | ||
+ | c.in_reply_to = None | ||
+ | </source> | ||
+ | |||
+ | Значение '''‘parent’''' из HTML-формы передается в метод '''post()'''. Затем для поиска объекта в хранилище данных используется метод '''db.Key()'''. Если посмотреть исходный код HTML, то вы увидите, | ||
+ | что ключи – это длинные строки, а не целые числа. | ||
+ | |||
+ | При попытке ответить на комментарий легко заметить, что ответы появляются внизу страницы, поэтому следующий шаг – это структурировать комментарии иерархически. Вам понадобится обновить ''GQL'', добавить файл '''comment.html''' и добавить метод в модель '''Comment'''. Назовем его '''get_replies''': | ||
+ | |||
+ | <source lang=python> | ||
+ | def get_replies(self): | ||
+ | comments = Comment.gql(“where in_reply_to =:1 ORDER BY date DESC LIMIT 10”, self) | ||
+ | return comments | ||
+ | </source> | ||
+ | |||
+ | {{Врезка|Заголовок=Индексы|Содержание=Как и в любом приложении, работающем с базой данных, при увеличении объемов информации нужно добавить индексы. Для этого пригодится файл '''index.yaml''', который будет создан за нас. Индексы требуются при сортировке, фильтрации по группам сущностей | ||
+ | и более сложных запросах. Начните отсюда: http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html.|Ширина=200px}} | ||
+ | |||
+ | Этот код возвращает все комментарии, являющиеся ответами на комментарий '''self'''. Комментариями верхнего уровня должны быть те, у которых поле '''in_reply_to''' не заполнено. Поэтому мы изменим ''GQL'' в методе '''get()''', воспользовавшись константой ''Python'' '''None''': | ||
+ | |||
+ | comments = Comment.gql(“WHERE in_reply_to =:1 ORDER BY date DESC“, None) | ||
+ | |||
+ | Если обновить страницу сейчас, вы увидите, что отображаются только комментарии верхнего уровня. Последний шаг – сделать '''comment.html''' иерархическим: | ||
+ | <source lang=xml> | ||
+ | <p> | ||
+ | {% for comment in comment.get_replies %} | ||
+ | {% include ‘comment.html’ %} | ||
+ | {% endfor %} </p> | ||
+ | </source> | ||
+ | |||
+ | Обновите страницу, чтобы увидеть вложенные комментарии. Кликните по ссылке '''Add Comment''', чтобы ответить на любой из комментариев. | ||
+ | |||
+ | ====Выгрузка вашего приложения==== | ||
+ | |||
+ | Для выгрузки используется еще одна утилита, '''appcfg.py'''. Нужно лишь указать опции команды '''update''' и местоположение приложения. | ||
+ | |||
+ | ~/appEngineProject/ $ appcfg.py update helloworld/ | ||
+ | Loaded authentication cookies from /Users/you/.appcfg_cookies | ||
+ | Scanning files on local disk. | ||
+ | Initiating update. | ||
+ | Email: some_user@gmail.com | ||
+ | Password for some_user@gmail.com: | ||
+ | Saving authentication cookies to /Users/you/.appcfg_cookies | ||
+ | Cloning 21 application files. | ||
+ | Uploading 5 files. | ||
+ | Closing update. | ||
+ | Uploading index definitions | ||
+ | |||
+ | У вас спросят параметры учетной записи Google, после чего приложение загрузится на серверы Google. '''LXF''' |
Текущая версия на 23:51, 19 февраля 2010
|
|
|
- Hardcore Linux Проверь себя на крутом проекте для продвинутых пользователей
Содержание |
[править] GAE: Создаем web-приложение
- С Google App Engine легко создавать масштабируемые приложения, не вникая в детали масштабирования. Дэн Фрост закинет программу в облака.
Google App Engine – платформа для разработки приложений в инфраструктуре Google. Как и другие масштабируемые платформы, она дает возможность разместить приложение на «облаке» (LXF108), не тратясь на содержание собственной серверной «фермы».
В отличие от других решений по облачным вычислениям, Google App Engine применяется только для создания web-приложений. Вы можете управлять web-страницами, хранить информацию и взаимодействовать с внешними web-серверами, но не имеете доступа к файлам, дискам и базам данных, как было бы в обычной среде.
Это может заставить вас изменить структуру приложения, но зато в вашем распоряжении будут очень мощные инструменты. Google App Engine поддерживает учетные записи Google, обработку изображений, огромные хранилища данных и взаимодействие с некоторыми службами Google посредством библиотеки Google Data Library.
Пока поддерживаются только приложения на языке Python. Если это не ваш любимый язык программирования – «следите за рекламой»: в будущем появятся и другие.
[править] Работа с App Engine
Сначала поработаем локально, пользуясь сервером разработчика dev_appserver.py, который имитирует реальную среду. Предоставляемая SDK, она включает работающий сервер, хранилище данных, псевдоучетные записи пользователей и все необходимое для создания приложения. Когда ваш новый шедевр Web 2.0 будет готов, разверните его на серверах Google с помощью скрипта appcfg.py, который загрузит программу на вашу учетную запись в App Engine (создайте ее на сайте http://appengine.google.com).
Пора установить среду разработки. Сначала позаботьтесь о наличии установленного Python 2.5, после чего можно загрузить App Engine для вашей ОС с сайта http://code.google.com/appengine/downloads.html. В Linux, распакуйте архив и добавьте App Engine в переменную окружения $PATH:
export PATH=$PATH:/path/to/google_appengine/
Проверьте, что это работает, набрав dev_appserver.py в командной строке – вы должны увидеть обычную страницу справки. Затем создайте каталог для своего приложения:
mkdir ~/myapp/
Теперь создайте файл ключа для App Engine: app.yaml. Он указывает App Engine, в каком каталоге находится приложение и как обращаться с каждым его файлом. Заполните ~/myapp/app.yaml таким содержимым:
application: mydemoapp version: 1 runtime: python api_version: 1 handlers: - url: /.* script: main.py
Этот файл сообщает App Engine, что имя приложения – mydemoapp, а все запросы должны передаваться скрипту main.py. Для обработки любого URL-адреса можно задать любой скрипт и даже применить шаблоны для использования различных файлов:
url: /browse/(.*?)/ script: /listings/\1.py
Приведенная выше конфигурация передает все в скрипт main.py, поэтому создайте этот файл и добавьте в него вывод традиционного сообщения:
print “Hello, World”
Наше скромное приложение готово. Запустите сервер с помощью скрипта dev_appserver.py и откройте в браузере адрес http://localhost:8080.
dev_appserver.py ~/myapp/
В App Engine допустимо большинство стандартных выражений Python; исключения в основном касаются доступа к файловой системе. Попробуйте добавить методы и классы, создайте модуль, и вы увидите, что среда вам знакома.
[править] Применение webapp
В состав App Engine входит MV-каркас webapp, позволяющий создавать хорошо структурированные приложения всего несколькими строками кода. Первая строка импортирует его, затем создается обработчик – это простой класс, унаследованный от webapp.RequestHandler:
from google.appengine.ext import webapp class ExampleApp(webapp.RequestHandler): def get(self): self.response.out.write(‘Hello, well structured world’)
В обработчике есть два важных метода – get() и post(). Первый вызывается для всех запросов HTTP GET, второй – для всех запросов HTTP POST. Следом за самим обработчиком запросов нужно зарегистрировать его в webapp и вызвать метод main() webapp:
application = webapp.WSGIApplication( [(‘/’, ExampleApp)], debug=True) def main(): run_wsgi_app(application) if __name__ == “__main__”: main()
Снова откройте в браузере URL приложения, и вы увидите весьма невыразительную строку текста. Давайте улучшим ее, переместив сообщение в шаблон – создайте файл index.html:
<html> <head><title>Hi there!</title></head> <body><h1>Hello from the template</h1></body> </html>
Затем подключите шаблон, изменив метод get():
def get(self): template_vars = {} self.response.out.write(template.render(path, template_vars))
Если вы хотите включить таблицы стилей, JavaScript, изображения или любые другие статические файлы, нужно предупредить об этом app.yaml. Добавьте в него следующие строки перед обработчиком url: /.*:
- url: /style static_dir: style
Затем создайте каталог style и файл app.css и включите их в index.html:
<link rel=“stylesheet” href=”/style/app.css” type=“text/css”>
Теперь можно добавить в CSS-файл какой-нибудь стиль – сделайте это сами.
[править] Сохранение моделей
Масштабирование баз данных – сложная задача, но Google нашел несколько умных способов ее решения, применив новый подход к традиционным реляционным БД.
BigTable от Google – сердце системы хранения данных App Engine. Это означает, что можно создавать приложения, способные масштабироваться до миллионов пользователей и страниц. BigTable – это распределенная система хранения, созданная для управления «петабайтами данных на тысячах стандартных серверов» (http://labs.google.com/papers/bigtable.html), но начать работать с ней в App Engine очень просто. Все начинается с моделей, создание которых требует несколько строчек кода. Модели в App Engine являются классами-расширениями db.Model. Их свойства аналогичны свойствам полей в таблицах обычных баз данных. Вот пример простой модели:
class MyNote(db.Model): thenote = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True)
В свойство date автоматически записывается текущее время благодаря методу auto_now_add, свойство thenote – просто строка. Типы параметров включают логический (boolean), целые числа (integer), числа с плавающей точкой (float), двоичные данные (blob), почтовые сообщения (emails) и другие.
Подготовка никакая не нужна – просто создайте экземпляр класса, установите его свойства и вызовите метод put():
note = MyNote() note.thenote = ”Just a quick note” note.put()
В нашем примере мы начнем с создания модели для хранения комментариев и назовем ее Comment:
class Comment(db.Model): content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) author = db.UserProperty()
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Теперь добавим в приложение немного данных, просмотрим их и установим им несколько интересных свойств. Чтобы добавить несколько комментариев, нужно создать форму, сохранить данные и затем отобразить их. Начнем с добавления формы в файл index.html:
<form action=”/” method=”post” accept-charset=”utf-8”> <input type=”hidden” name=”parent” value=”{{ comment.key }}” /> <textarea name=”comment”></textarea> <input type=”submit” value=”Add”></div> </form>
Затем добавим метод post() в контроллер.
def post(self): c = Comment() c.content = self.request.get(‘comment’) c.author = users.get_current_user() c.put() self.redirect(‘/’)
Для извлечения данных из хранилища используется GQL, и по большей части он похож на SQL. Вам нужно заменить содержимое метода get() вызовом метода GQL класса Comment, который затем передать в шаблон:
comments = Comment.gql(“ORDER BY date DESC“) template_vars = { ‘comments’: comments } self.response.out.write(template.render(‘index.html’,template_vars))
Наконец, можно пройтись по комментариям и отобразить их:
{% for comment in comments %} <p>{{ comment.content }}</p> {% endfor %}
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Для ясности и простоты добавления нового функционала переместите строку с обработкой комментариев в другой файл. Замените вторую строку из последнего примера на { % include ‘comment.html’ %} и создайте файл comment.html со следующим содержимым:
<div class=“comment row1”> <p><strong�Posted on {{ comment.date }}</strong><br /> {{ comment.content }} </p> </div>
[править] Использование пользователей
App Engine позволяет аутентифицировать пользователей по существующим учетным записям Google, и вашим посетителям нет нужды регистрироваться заново ради очередного web-приложения. Для всего этого используется пакет users:
from google.appengine.api import users
Теперь можно получить доступ к имени пользователя и его email-адресу с помощью функции users.get_current_user(). Если пользователь еще не вошел в систему, можно перенаправить его на форму входа:
if users.get_current_user(): user = get_current_user() self.response.out.write(“You are logged in as: “ + user. nickname()) else: self.redirect(users.create_login_url(“/home”))
Параметр /home – это URL, на который вы направляете пользователя после входа в систему.
В приложении обработки комментариев можно заставить пользователей регистрироваться, прежде чем начинать что-либо писать; перенаправим их на страницу входа:
if users.get_current_user(): comments = �omment.gql(“WHERE in_reply_to =:1 ORDER BY date DESC“, None) template_vars = { ‘comments’: comments } self.response.out.write(template.render(‘index.html’, template_vars)) else: message = (“<a href=’ %s’>Please login</a>.” %users. create_login_url(“/rels”)) self.response.out.write(message)
Обновите приложение в браузере, чтобы убедиться, что аутентификация работает.
Теперь, когда пользователи вошли в систему, сохраняйте авторов всех комментариев, добавив следующую строку в метод post() перед командой c.put():
c.author = users.get_current_user()
Чтобы вывести имя и e-mail автора комментария, добавьте следующие строки в файл comment.html:
<p><b>Posted by: <b> {% if comment.author.nickname %} {{ comment.author.nickname }} ({{ comment.author.email }}) {% else %} Anonymous {% endif %} on {{ comment.date }} </p>
[править] Связанные сущности
Отношения между сущностями задаются внутри модели с помощью метода ReferenceProperty, который ссылается на другую модель, или SelfReferenceProperty, который ссылается на текущую. Связать одну модель с другой можно примерно так:
related_thing = db.ReferenceProperty(OtherThing)
Если вы хотите, чтобы пользователи могли отвечать на сообщения, оставленные на доске объявлений, у каждого комментария должен быть родитель _parent_, которого мы назовем in_reply_to. Объявите это свойство, добавив в модель �omment следующую строку:
in_reply_to = db.SelfReferenceProperty()
Теперь можно добавить форму для каждого существующего комментария:
<div> <div id=“comment-{{ comment.key }}” style=“display:none;”> <form action=“/rels” method=“post” acceptcharset=“utf-8”> <input type=“hidden” name=“parent” value=”{{ comment.key }}” /> <textarea name=“comment” rows=“7” cols=”30”></textarea> <input type=“submit” value=“Add”> </form> </div> <a href=“javascript:document.getElementById(‘comment-{{comment.key}}’).style.display=’block’;”>Add comment</a> </div>
…а затем изменить метод post(), чтобы сохранить его:
if self.request.get(‘parent’): key_name = self.request.get(‘parent’) p = db.get(db.Key(key_name)) c.in_reply_to = p else: c.in_reply_to = None
Значение ‘parent’ из HTML-формы передается в метод post(). Затем для поиска объекта в хранилище данных используется метод db.Key(). Если посмотреть исходный код HTML, то вы увидите, что ключи – это длинные строки, а не целые числа.
При попытке ответить на комментарий легко заметить, что ответы появляются внизу страницы, поэтому следующий шаг – это структурировать комментарии иерархически. Вам понадобится обновить GQL, добавить файл comment.html и добавить метод в модель Comment. Назовем его get_replies:
def get_replies(self): comments = Comment.gql(“where in_reply_to =:1 ORDER BY date DESC LIMIT 10”, self) return comments
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Этот код возвращает все комментарии, являющиеся ответами на комментарий self. Комментариями верхнего уровня должны быть те, у которых поле in_reply_to не заполнено. Поэтому мы изменим GQL в методе get(), воспользовавшись константой Python None:
comments = Comment.gql(“WHERE in_reply_to =:1 ORDER BY date DESC“, None)
Если обновить страницу сейчас, вы увидите, что отображаются только комментарии верхнего уровня. Последний шаг – сделать comment.html иерархическим:
<p> {% for comment in comment.get_replies %} {% include ‘comment.html’ %} {% endfor %} </p>
Обновите страницу, чтобы увидеть вложенные комментарии. Кликните по ссылке Add Comment, чтобы ответить на любой из комментариев.
[править] Выгрузка вашего приложения
Для выгрузки используется еще одна утилита, appcfg.py. Нужно лишь указать опции команды update и местоположение приложения.
~/appEngineProject/ $ appcfg.py update helloworld/ Loaded authentication cookies from /Users/you/.appcfg_cookies Scanning files on local disk. Initiating update. Email: some_user@gmail.com Password for some_user@gmail.com: Saving authentication cookies to /Users/you/.appcfg_cookies Cloning 21 application files. Uploading 5 files. Closing update. Uploading index definitions
У вас спросят параметры учетной записи Google, после чего приложение загрузится на серверы Google. LXF