tag:blogger.com,1999:blog-205688732024-03-13T20:53:00.830+04:00Мысли вслухOracle, Python, Django и просто за жизнь.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.comBlogger49125tag:blogger.com,1999:blog-20568873.post-58248037968928600312020-11-03T20:31:00.000+04:002020-11-03T20:31:02.928+04:00 Возвращение к Oracle. Особенности сборки cx_Oracle под AIX 7.1<p><br /></p><p>Добрый день всем!</p><p>Я вернулся из OpenSource в кровавый ентерпрайз и продолжаю бороться со всякими препятствиями.</p><p>Коротко - дано:</p><p>OracleDb сервер на AIX 7.1.</p><p>Задача: сделать мониторинг как самой базы, так и различных бизнес-сущностей. </p><p>Решение: первую версию мониторинга накатал на shell через sqlplus. Проблем несколько:</p><p></p><ul style="text-align: left;"><li>отсутствие постоянного соединения с базой</li><li>сложность в добавлении всяких discovery items для Zabbix</li></ul><div>Вторую версию сделал на golang - но к сожалению, сборка стандартными средствами через GOOS=aix работает только на версии AIX 7.2, а у меня - 7.1 Позже дерну наших сишников, скорее всего соберут. На данный момент ждать не могу, надо сделать задачу хотя бы в первом приближении. </div><div><br /></div><div>Ok, ставим python3 под AIX из IBM AixToolbox, накатываю instantclient с помощью Ansible, </div><div>начинаю собирать cx_Oracle:</div><div><br /></div><div><br /></div><div>```</div><div></div><blockquote><div>/opt/freeware/bin/python3 setup.py build</div><div>/opt/freeware/bin/python3 setup.py install</div></blockquote><div></div><p></p><p>```</p><p><br /></p><p>Сборка проходит без особых проблем, а вот на install загвоздка:</p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;"></p><blockquote>ValueError: ZIP does not support timestamps before 1980</blockquote><p></p></blockquote><p>Лезем в /opt/freeware/lib64/python3.7/zipfile.py, вставляем print на имя файла и дату, видим следующую картину:</p><p><span> </span>cx_Oracle-doc/LICENSE.txt</p><p><span> </span>(1970, 1, 1, 1, 0, 0)</p><p> Ха, лицензия без даты. И не только она. Делаем find . -type f -exec touch {} \;</p><p>Повторяем install --user - profit!!!</p><p>Только почему-то директория .local/lib/python3.7 пустая. </p><p>Вручную копирую туда пакет и либу:</p><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"><p>cp cx_Oracle-8.0.1/build/lib.aix-7.1-3.7/cx_Oracle.so .local/lib/python3.7/site-packages/</p><p>cp cx_Oracle-8.0.1/dist/cx_Oracle-8.0.1-py3.7-aix-7.1.egg .local/lib/python3.7/site-packages/</p></blockquote><p>Ставим PYTHONPATH </p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;">export PYTHONPATH=~/.local/lib/python3.7/</p></blockquote><p>Запускаем python3, проверяем:</p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><p style="text-align: left;">>>> import cx_Oracle</p></blockquote><p> >>> connection = cx_Oracle.connect("scott", "tiger", "mydb")</p><p> >>> cursor = connection.cursor()</p><p> >>> cursor.execute("""select sysdate from dual""")</p><p> <cx_Oracle.Cursor on <cx_Oracle.Connection to scott@mydb>></p><p><span> <span> </span></span>>>> print(cursor.fetchone())</p><p><span> <span> </span></span>(datetime.datetime(2020, 11, 3, 17, 29, 14),)</p><p>Работает!</p><p><br /></p>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-79552764689204703772017-04-06T15:46:00.000+04:002017-04-06T15:46:25.048+04:00WakaTime - еще один сервис учета;<div dir="ltr" style="text-align: left;" trbidi="on">
В недрах <a href="https://habrahabr.ru/company/JetBrains/blog/317716/" target="_blank">Goglang</a> нашел плагин <a href="https://wakatime.com/" target="_blank">WakaTime</a>, cходил на сайт, зарегистрировался. Вобщем, сервис считает, сколько времени на каких языках программирования вы работаете; В бесплатной версии сервис хранит данные за неделю, хотите серьезной статистики - платите. Есть плагины к большинству популярных IDE, даже vim в списке, но на моем Маке этот плагин не завелся.<br />
<br />
Вот такие картинки можно шарить:<br />
<a href="https://wakatime.com/"><img height="240" src="https://wakatime.com/share/@69c37328-2169-4672-8253-231df71bb370/f6ca942f-d7d9-404b-8238-e424c1f07d11.png" width="320" /></a>
<br />
<br />
Плохо пока с распознаванием PL/SQL - но, думаю, доточат.<br />
Так же сервис позволяет ставить цели, вот иду к цели довести разработку на Go до 50%, посмотрим, что получится<br />
<br />
Люблю все считать, поэтому задумываюсь о покупке аккаунта.</div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com1tag:blogger.com,1999:blog-20568873.post-52121547042770432192017-03-12T12:28:00.000+04:002017-03-12T12:28:05.130+04:00Pyston 0.6.1 - всё<div dir="ltr" style="text-align: left;" trbidi="on">
http://www.opennet.ru/opennews/art.shtml?num=45984<br />
<blockquote class="tr_bq">
<span style="background-color: #e9ead6; font-family: sans-serif; font-size: 16px; text-indent: 20px;">К сожалению дальнейшее развитие проекта будет зависеть от интереса к нему независимого сообщества - компания Dropbox приняла решение прекратить разработку своими силами и Pyston 0.6.1 стал последним релизом, подготовленным инженерами Dropbox в своё основное рабочее время. Проанализировав состояние проекта компания пришла к выводу, что на поддержание совместимости с CPython и обеспечение приемлемого потребления памяти требуется значительно больше ресурсов и затрат, чем ожидалось. Но решающим фактором отказа от проекта Pyston стали не оправдавшиеся завышенные надежды на производительность Pyston.</span></blockquote>
<span style="background-color: #e9ead6; font-family: sans-serif; font-size: 16px; text-indent: 20px;">В итоге, более реалистичным путём оптимизации в Dropbox стала переработка кода, требующего высокой производительности, на других языках, таких как Go.</span><br />
<br />
Комментарий - три месяца назад начал активно изучать Go, в силу того, что дальнейшие перспективы Python в качестве основного инструмента для интеграции остаются для меня достаточно туманными. 2.7 ветка конечно же проживет еще лет 5-10 в силу инерции, но лучше уже сейчас начинать потихоньку выносить все, что возможно на GoLang.<br />
Так, сейчас я в процессе миграции всех DevOps веб-сервисов c Flask/Bottle на <a href="http://revel.github.io/" target="_blank">Revel</a> </div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-91151287741349975892017-03-12T12:27:00.001+04:002017-03-12T12:27:30.139+04:00Бага в Revel 1.3 на Prod<div dir="ltr" style="text-align: left;" trbidi="on">
Добрый!<br />
Продолжаем миграцию с Python на Go.<br />
После генерации дюжины микросервисов на Revel + MongoDB я наконец решил задействовать GUI revel. После Django ничего сложного, единственно, http/template показался мне хилым после Jinja2. Ну да какие наши годы - все течет и становится лучше.<br />
<br />
Написал простую страницу с логином через AD - вывел несколько таблиц с данными по текущим сборкам и свободным ресурсам.<br />
<br />
Пройдя все локальные тесты, решил выложить все на production, для этого сделал систему развертывания на старом добром<a href="http://www.fabfile.org/" target="_blank"> Fabric</a> (аналого на Go пока не нашел), сборка архива после тестов GitLab CI, отправка на сервера, распаковка, рестарт приложения через sudo service - все стандартно.<br />
<br />
Ок, вроде все работает, заходим на стартовую страницу, логинимся и - нет логина. В конфиге включаем трассировку, видим, что проверка логина/пароля через LDAP проходит, но - кука авторизованной сессии не ставится.<br />
<br />
Час на разбор кишок revel (в Go я все еще Beginner), находим багу в revel, затем поиском находим эту же багу в трекере проекта - https://github.com/revel/revel/issues/1097<br />
<br />
Вобщем, простой путь - лезем в кишки revel - у меня это $GOPATH/src/github.com/revel/revel/revel.go, в строке 207 меняем<br />
<br />
<blockquote class="tr_bq">
<span style="color: #24292e; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 11.899999618530273px;">CookieSecure = Config.BoolDefault("cookie.secure", !DevMode)</span> </blockquote>
на<br />
<blockquote class="tr_bq">
<span style="color: #24292e; font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 11.899999618530273px;">CookieSecure = Config.BoolDefault("cookie.secure", false)</span> </blockquote>
<br />
Пересобираем бинарник и все работает. </div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-23870137259859294222017-02-06T12:22:00.002+04:002017-03-12T11:45:50.037+04:00Генерируем RESTFul App на REVEL+MongoDB за 10 мин <div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<span style="font-size: 18px;">Сохранено с </span>https://medium.com/@kyawmyintthein/revel-mgo-restful-generator-for-revel-web-framework-mongodb-86209de3977e#.7pv1rjo3g</div>
<h1 class="title" style="-webkit-hyphens: manual; color: #1b1b1b; font-family: Georgia; font-weight: 400; line-height: 1.2em; margin-bottom: 0.5em; margin-top: 0px; max-width: 100%;">
<span style="font-size: 18px;">This article is about a generator called</span><span style="font-size: 18px;"> </span><strong style="font-size: 18px; max-width: 100%;">revel_mgo. </strong><span style="font-size: 18px;">It is developed my me. And then, It is mainly focus for Restful API. I would like to share that generator in this article.</span></h1>
<h4 name="1539" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; margin: 1em 0px; max-width: 100%;">
Requirement</h4>
<div name="df1b" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
First of all, this generator is specifically for Revel Web Framework <a data-href="https://revel.github.io/" href="https://revel.github.io/" rel="nofollow" style="color: #416ed2; max-width: 100%; text-decoration: none;" target="_blank">https://revel.github.io/</a>. Revel is a high productivity, full-stack web framework for the Go language. But, it is not dependent on Revel framework. So, you might use in other framework. But, The main problem might be directory structure because this is based on revel framework structure. Then, It is only for mongo database.</div>
<h4 name="1b4b" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; margin: 1em 0px; max-width: 100%;">
Why I develop this generator?</h4>
<div name="6112" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
<strong style="max-width: 100%;">Revel</strong> is good web framework. But, I cannot find generator like Ruby on Rails. If you implement your system, it might take some time.</div>
<h4 name="6a45" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; margin: 1em 0px; max-width: 100%;">
About</h4>
<div name="77b2" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
<strong style="max-width: 100%;">revel_mgo</strong> generator is very simple. It will generate the some files for your Restful App. And, it is customizable. You can customize generated files in your project. It will generate mongodb setup files, models and controllers.</div>
<h4 name="8e78" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; margin: 1em 0px; max-width: 100%;">
How to use this generator?</h4>
<div name="bc2a" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
At first, you need to install revel framework and revel command in your machine. You can follow this <a data-href="https://revel.github.io/tutorial/gettingstarted.html" href="https://revel.github.io/tutorial/gettingstarted.html" rel="nofollow" style="color: #416ed2; max-width: 100%; text-decoration: none;" target="_blank">https://revel.github.io/tutorial/gettingstarted.html</a> link for revel framework.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="f09c" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">go get github.com/revel/revel
go get github.com/revel/cmd/revel</pre>
</div>
<div name="4546" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
After that, you can user revel command.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="9eb2" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">$ revel help
~
~ revel! http://revel.github.io
~
usage: revel command [arguments]
The commands are:
new create a skeleton Revel application
run run a Revel application
build build a Revel application (e.g. for deployment)
package package a Revel application (e.g. for deployment)
clean clean a Revel application's temp files
test run all tests from the command-line
Use "revel help [command]" for more information.</pre>
</div>
<div name="9d37" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
You can create revel project and run by using following command.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="a62e" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">$ revel new myapp
~
~ revel! http://revel.github.io
~
Your application is ready:
/home/me/gostuff/src/myapp
You can run it with:
revel run myapp
$ revel run myapp
~
~ revel! http://revel.github.io
~
2012/09/27 17:01:54 run.go:41: Running myapp <strong style="max-width: 100%;">(</strong>myapp<strong style="max-width: 100%;">)</strong> <strong style="max-width: 100%;">in </strong>dev mode
2012/09/27 17:01:54 harness.go:112: Listening on :9000</pre>
</div>
<div name="990a" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Now your project on on localhost:9000</div>
<div name="298f" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Now let install revel_mgo.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="5084" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">go get github.com/kyawmyintthein/revel_mgo</pre>
</div>
<div name="f075" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Now revel_mgo command is avaliable. So, you can setup mongo by using :</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="0453" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">$cd myapp
$revel_mgo</pre>
</div>
<br />
<figure class="clear" name="b07c" style="clear: both; color: rgba(0, 0, 0, 0.65098); font-family: -apple-system-font; font-size: 0.75em; line-height: 1.5em; margin: 1.4em 0px; max-width: 100%;"><div style="max-width: 100%;">
<div data-action-value="1*oohNmTVIZseAhEGJ_AMPgw.png" data-action="zoom" data-height="388" data-image-id="1*oohNmTVIZseAhEGJ_AMPgw.png" data-scroll="native" data-width="1626" style="max-width: 100%;">
<img class="extendsBeyondTextColumn" data-src="https://cdn-images-1.medium.com/max/800/1*oohNmTVIZseAhEGJ_AMPgw.png" src="https://cdn-images-1.medium.com/max/800/1*oohNmTVIZseAhEGJ_AMPgw.png" style="-webkit-margin-start: -62.703125px; display: block; height: auto; margin: 0.5em auto; max-width: none; width: 800px;" /></div>
</div>
</figure><br />
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="b657" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">$revel_mgo mgo:setup</pre>
</div>
<br />
<figure class="clear" name="00b9" style="clear: both; color: rgba(0, 0, 0, 0.65098); font-family: -apple-system-font; font-size: 0.75em; line-height: 1.5em; margin: 1.4em 0px; max-width: 100%;"><div style="max-width: 100%;">
<div data-action-value="1*gl0oy5OlCDpewTOq4DYnvg.png" data-action="zoom" data-height="332" data-image-id="1*gl0oy5OlCDpewTOq4DYnvg.png" data-scroll="native" data-width="1832" style="max-width: 100%;">
<img class="extendsBeyondTextColumn" data-src="https://cdn-images-1.medium.com/max/800/1*gl0oy5OlCDpewTOq4DYnvg.png" src="https://cdn-images-1.medium.com/max/800/1*gl0oy5OlCDpewTOq4DYnvg.png" style="-webkit-margin-start: -62.703125px; display: block; height: auto; margin: 0.5em auto; max-width: none; width: 800px;" /></div>
</div>
</figure><br />
<div name="790d" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Now mongo setup files are already in your project. But, you need change some code to start mongo in your Revel project.</div>
<div name="295c" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
You need to add this code in your conf/app.conf</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="a3d1" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">[dev] //it is already in app.conf
mongo.database = database_name
mongo.path = localhost
mongo.maxPool = 20</pre>
</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="3844" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">[pro] //it is already in app.conf
mongo.database = pro_database_name
mongo.path = localhost
mongo.maxPool = 20</pre>
</div>
<div name="81ea" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Then, add this function in your inti.go.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="fee3" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">func initApp() {
<span style="background-color: magenta;"> Config, err := revel.LoadConfig("app.conf")
if err != nil || Config == nil {
log.Fatalf("%+v",err)
} -- эта часть лишняя для revel 1.3</span>
mongodb.MaxPool = revel.Config.IntDefault("mongo.maxPool", 0)
mongodb.PATH,_ = revel.Config.String("mongo.path")
mongodb.DBNAME, _ = revel.Config.String("mongo.database")
mongodb.CheckAndInitServiceConnection()
}</pre>
</div>
<div name="c86c" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
And then, call initApp() function on Revel start.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="77d5" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">revel.OnAppStart(initApp)</pre>
</div>
<div name="4b4d" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Now, you might need to create mongodb database. After setup the mongodb, you can generate the model for your application. To generate models you can use “revel_mgo generate” command. So, use following command to generate sample model.</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="8502" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">revel_mgo generate model Post -fields=title:string,content:string</pre>
</div>
<br />
<figure class="clear" name="6ca3" style="clear: both; color: rgba(0, 0, 0, 0.65098); font-family: -apple-system-font; font-size: 0.75em; line-height: 1.5em; margin: 1.4em 0px; max-width: 100%;"><div style="max-width: 100%;">
<div data-action-value="1*DO1J4w4puFHPs-t2yo9Jfw.png" data-action="zoom" data-height="236" data-image-id="1*DO1J4w4puFHPs-t2yo9Jfw.png" data-scroll="native" data-width="1580" style="max-width: 100%;">
<img class="extendsBeyondTextColumn" data-src="https://cdn-images-1.medium.com/max/800/1*DO1J4w4puFHPs-t2yo9Jfw.png" src="https://cdn-images-1.medium.com/max/800/1*DO1J4w4puFHPs-t2yo9Jfw.png" style="-webkit-margin-start: -62.703125px; display: block; height: auto; margin: 0.5em auto; max-width: none; width: 800px;" /></div>
</div>
</figure><br />
<div name="173b" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
The “Post” model file is generated in your models folder. It will include id, createdAt and updatedAt by default. Then, It will also include CRUD function for your model using mongodb. You can also add your own function and update existing functions.</div>
<blockquote name="0491" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
package models</blockquote>
<blockquote name="5969" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
import (<br />
“gopkg.in/mgo.v2/bson”<br />
“myapp/app/models/mongodb”<br />
“time”<br />
)</blockquote>
<blockquote name="0368" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
type Post struct {<br />
ID bson.ObjectId `json:”id” bson:”_id”`<br />
Title string `json:”title” bson:”title”`<br />
Content string `json:”content” bson:”content”`<br />
CreatedAt time.Time `json:”created_at” bson:”created_at”`<br />
UpdatedAt time.Time `json:”updated_at” bson:”updated_at”`<br />
}</blockquote>
<blockquote name="63dc" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func newPostCollection() *mongodb.Collection {<br />
return mongodb.NewCollectionSession(“posts”)<br />
}</blockquote>
<blockquote name="2ed3" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
// AddPost insert a new Post into database and returns<br />
// last inserted post on success.<br />
func AddPost(m Post) (post Post, err error) {<br />
c := newPostCollection()<br />
defer c.Close()<br />
m.ID = bson.NewObjectId()<br />
m.CreatedAt = time.Now()<br />
return m, c.Session.Insert(m)<br />
}</blockquote>
<blockquote name="5911" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
// UpdatePost update a Post into database and returns<br />
// last nil on success.<br />
func (m Post) UpdatePost() error {<br />
c := newPostCollection()<br />
defer c.Close()</blockquote>
<blockquote name="6bc0" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
err := c.Session.Update(bson.M{<br />
“_id”: m.ID,<br />
}, bson.M{<br />
“$set”: bson.M{<br />
“title”: m.Title, “content”: m.Content, “updatedAt”: time.Now()},<br />
})<br />
return err<br />
}</blockquote>
<blockquote name="0f4c" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
// DeletePost Delete Post from database and returns<br />
// last nil on success.<br />
func (m Post) DeletePost() error {<br />
c := newPostCollection()<br />
defer c.Close()</blockquote>
<blockquote name="5fdb" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
err := c.Session.Remove(bson.M{“_id”: m.ID})<br />
return err<br />
}</blockquote>
<blockquote name="a283" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
// GetPosts Get all Post from database and returns<br />
// list of Post on success<br />
func GetPosts() ([]Post, error) {<br />
var (<br />
posts []Post<br />
err error<br />
)</blockquote>
<blockquote name="eed3" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
c := newPostCollection()<br />
defer c.Close()</blockquote>
<blockquote name="b31a" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
err = c.Session.Find(nil).Sort(“-createdAt”).All(&posts)<br />
return posts, err<br />
}</blockquote>
<blockquote name="1da9" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
// GetPost Get a Post from database and returns<br />
// a Post on success<br />
func GetPost(id bson.ObjectId) (Post, error) {<br />
var (<br />
post Post<br />
err error<br />
)</blockquote>
<blockquote name="8c29" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
c := newPostCollection()<br />
defer c.Close()</blockquote>
<blockquote name="2618" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
err = c.Session.Find(bson.M{“_id”: id}).One(&post)<br />
return post, err<br />
}</blockquote>
<div name="9cdf" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Controller also can generated by using:</div>
<div class="scrollable extendsBeyondTextColumn" style="-webkit-margin-start: -0.203125px; color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: none; overflow-x: scroll; width: 675px; word-wrap: normal;">
<pre name="269e" style="font-size: 0.93em; line-height: 1.5em; max-width: 100%;">revel_mgo generate controller Post</pre>
</div>
<br />
<figure class="clear" name="4e1d" style="clear: both; color: rgba(0, 0, 0, 0.65098); font-family: -apple-system-font; font-size: 0.75em; line-height: 1.5em; margin: 1.4em 0px; max-width: 100%;"><div style="max-width: 100%;">
<div data-action-value="1*OLEnqpWuKqKt8boL_slRzw.png" data-action="zoom" data-height="162" data-image-id="1*OLEnqpWuKqKt8boL_slRzw.png" data-scroll="native" data-width="1736" style="max-width: 100%;">
<img class="extendsBeyondTextColumn" data-src="https://cdn-images-1.medium.com/max/800/1*OLEnqpWuKqKt8boL_slRzw.png" src="https://cdn-images-1.medium.com/max/800/1*OLEnqpWuKqKt8boL_slRzw.png" style="-webkit-margin-start: -62.703125px; display: block; height: auto; margin: 0.5em auto; max-width: none; width: 800px;" /></div>
</div>
</figure><br />
<div name="20c2" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
The “PostController” is generated and it is inherit from revel controller. It will include Index, Create, Update, Show, Delete functions by using “Post” model. It is also generate “CommonController” if is does not exist. “CommonController” is used for some helper functions.</div>
<div name="406a" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
<strong style="max-width: 100%;">CommonController</strong></div>
<blockquote name="b0b3" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
package controllers</blockquote>
<blockquote name="f385" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
import (<br />
“fmt”<br />
“gopkg.in/mgo.v2/bson”<br />
“strconv”<br />
)</blockquote>
<blockquote name="3f93" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
type CtrlErr map[string]interface{}</blockquote>
<blockquote name="e602" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func parseUintOrDefault(intStr string, _default uint64) uint64 {<br />
if value, err := strconv.ParseUint(intStr, 0, 64); err != nil {<br />
return _default<br />
} else {<br />
return value<br />
}<br />
}</blockquote>
<blockquote name="fe7a" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func parseIntOrDefault(intStr string, _default int64) int64 {<br />
if value, err := strconv.ParseInt(intStr, 0, 64); err != nil {<br />
return _default<br />
} else {<br />
return value<br />
}<br />
}</blockquote>
<blockquote name="7e9d" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func convertToObjectIdHex(id string) (result bson.ObjectId, err error) {<br />
defer func() {<br />
if r := recover(); r != nil {<br />
err = fmt.Errorf(“Unable to convert %v to object id”, id)<br />
}<br />
}()</blockquote>
<blockquote name="0694" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
return bson.ObjectIdHex(id), err<br />
}</blockquote>
<blockquote name="51d8" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func buildErrResponse(err error, errorCode string) CtrlErr {<br />
ctrlErr := CtrlErr{}<br />
ctrlErr[“error_message”] = err.Error()<br />
ctrlErr[“error_code”] = errorCode<br />
return ctrlErr<br />
}</blockquote>
<div name="af65" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
<strong style="max-width: 100%;">PostController</strong></div>
<blockquote name="b255" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
package controllers</blockquote>
<blockquote name="cc1b" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
import (<br />
“encoding/json”<br />
“errors”<br />
“github.com/revel/revel”<br />
“gopkg.in/mgo.v2/bson”<br />
“myapp/app/models”<br />
)</blockquote>
<blockquote name="bb7f" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
type PostController struct {<br />
*revel.Controller<br />
}</blockquote>
<blockquote name="fd6d" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func (c PostController) Index() revel.Result {<br />
var (<br />
posts []models.Post<br />
err error<br />
)<br />
posts, err = models.GetPosts()<br />
if err != nil {<br />
errResp := buildErrResponse(err, “500”)<br />
c.Response.Status = 500<br />
return c.RenderJson(errResp)<br />
}<br />
c.Response.Status = 200<br />
return c.RenderJson(posts)<br />
}</blockquote>
<blockquote name="22bc" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func (c PostController) Show(id string) revel.Result {<br />
var (<br />
post models.Post<br />
err error<br />
postID bson.ObjectId<br />
)</blockquote>
<blockquote name="6e75" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
if id == “” {<br />
errResp := buildErrResponse(errors.New(“Invalid post id format”), “400”)<br />
c.Response.Status = 400<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="b677" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
postID, err = convertToObjectIdHex(id)<br />
if err != nil {<br />
errResp := buildErrResponse(errors.New(“Invalid post id format”), “400”)<br />
c.Response.Status = 400<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="009f" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
post, err = models.GetPost(postID)<br />
if err != nil {<br />
errResp := buildErrResponse(err, “500”)<br />
c.Response.Status = 500<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="a5e8" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
c.Response.Status = 200<br />
return c.RenderJson(post)<br />
}</blockquote>
<blockquote name="54eb" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func (c PostController) Create() revel.Result {<br />
var (<br />
post models.Post<br />
err error<br />
)</blockquote>
<blockquote name="0d39" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
err = json.NewDecoder(c.Request.Body).Decode(&post)<br />
if err != nil {<br />
errResp := buildErrResponse(err, “403”)<br />
c.Response.Status = 403<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="6ed0" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
post, err = models.AddPost(post)<br />
if err != nil {<br />
errResp := buildErrResponse(err, “500”)<br />
c.Response.Status = 500<br />
return c.RenderJson(errResp)<br />
}<br />
c.Response.Status = 201<br />
return c.RenderJson(post)<br />
}</blockquote>
<blockquote name="ced8" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func (c PostController) Update() revel.Result {<br />
var (<br />
post models.Post<br />
err error<br />
)<br />
err = json.NewDecoder(c.Request.Body).Decode(&post)<br />
if err != nil {<br />
errResp := buildErrResponse(err, “400”)<br />
c.Response.Status = 400<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="3a35" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
err = post.UpdatePost()<br />
if err != nil {<br />
errResp := buildErrResponse(err, “500”)<br />
c.Response.Status = 500<br />
return c.RenderJson(errResp)<br />
}<br />
return c.RenderJson(post)<br />
}</blockquote>
<blockquote name="7eea" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
func (c PostController) Delete(id string) revel.Result {<br />
var (<br />
err error<br />
post models.Post<br />
postID bson.ObjectId<br />
)<br />
if id == “” {<br />
errResp := buildErrResponse(errors.New(“Invalid post id format”), “400”)<br />
c.Response.Status = 400<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="14a6" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
postID, err = convertToObjectIdHex(id)<br />
if err != nil {<br />
errResp := buildErrResponse(errors.New(“Invalid post id format”), “400”)<br />
c.Response.Status = 400<br />
return c.RenderJson(errResp)<br />
}</blockquote>
<blockquote name="c902" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
post, err = models.GetPost(postID)<br />
if err != nil {<br />
errResp := buildErrResponse(err, “500”)<br />
c.Response.Status = 500<br />
return c.RenderJson(errResp)<br />
}<br />
err = post.DeletePost()<br />
if err != nil {<br />
errResp := buildErrResponse(err, “500”)<br />
c.Response.Status = 500<br />
return c.RenderJson(errResp)<br />
}<br />
c.Response.Status = 204<br />
return c.RenderJson(nil)<br />
}</blockquote>
<div name="78c2" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
To use PostController, you need to add routes in your conf/routes file.</div>
<blockquote name="7b95" style="border-left-color: rgba(0, 0, 0, 0.0980392); border-left-style: solid; border-left-width: 3px; color: rgba(0, 0, 0, 0.65098); font-family: Georgia; font-size: 18px; font-style: italic; margin-left: 2px; margin-right: 6px; max-width: 100%; padding-left: 16px;">
GET /posts PostController.Index<br />
POST /posts PostController.Create<br />
PUT /posts PostController.Update<br />
GET /posts/:id PostController.Show<br />
DELETE /posts/:id PostController.Delete</blockquote>
<div name="d411" style="color: #1b1b1b; font-family: Georgia; font-size: 18px; max-width: 100%;">
Then, Run your application.</div>
</div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-49333290726392067582015-04-25T13:02:00.000+04:002015-04-25T13:02:09.771+04:00Django makemigrations в PyCharm<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div>
<pre class="wikicode prettyprint prettyprinted" style="background-color: #f9f9f9; border: 1px dashed rgb(47, 111, 171); font-family: Menlo, 'Bitstream Vera Sans Mono', Consolas, 'Lucida Console', 'Courier New', Courier, monospace; font-size: 14px; line-height: 17px; max-height: 400px; overflow: auto; padding: 2px;"><span class="pln">code </span><span class="pun" style="color: #666600;">=</span><span class="pln"> input</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">">>> "</span><span class="pun" style="color: #666600;">).</span><span class="pln">decode</span><span class="pun" style="color: #666600;">(</span><span class="pln">sys</span><span class="pun" style="color: #666600;">.</span><span class="pln">stdin</span><span class="pun" style="color: #666600;">.</span><span class="pln">encoding</span><span class="pun" style="color: #666600;">)</span>
<span class="typ" style="color: #660066;">TypeError</span><span class="pun" style="color: #666600;">:</span><span class="pln"> decode</span><span class="pun" style="color: #666600;">()</span><span class="pln"> argument </span><span class="lit" style="color: #006666;">1</span><span class="pln"> must be </span><span class="kwd" style="color: #000088;">string</span><span class="pun" style="color: #666600;">,</span><span class="pln"> </span><span class="kwd" style="color: #000088;">not</span><span class="pln"> </span><span class="kwd" style="color: #000088;">None</span></pre>
</div>
<div>
<br /></div>
<div>
Если попытаться сделать миграцию для модели с новым полем без значения по умолчанию:</div>
<div>
<div>
<br /></div>
<div>
You are trying to add a non-nullable field 'slug' to catalog without a default;</div>
<div>
we can't do that (the database needs something to populate existing rows).</div>
<div>
Please select a fix:</div>
<div>
1) Provide a one-off default now (will be set on all existing rows)</div>
<div>
2) Quit, and let me add a default in models.py</div>
</div>
<div>
<br /></div>
<div>
Ну вобщем в консоли PyCharm это не работает, используйте обычную командную строку.</div>
<div>
<br /></div>
<div>
Проверено на версии Django 1.7</div>
</div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com2tag:blogger.com,1999:blog-20568873.post-20886996831977932882013-04-16T13:11:00.003+04:002013-04-16T13:11:40.472+04:00Оно работает - 64 Oracle instance client на Max OS X <div dir="ltr" style="text-align: left;" trbidi="on">
Установка, как обычно - копируем в папку и выставляем путь к папке в DYLD_LIBRARY_PATH - я это делаю в /etc/profile.<br />
<br />
Осталось только вспомнить и откатить настройки Python, которые я делал, чтобы использовать 32 битную cx_Oracle. </div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-2630530501154980922013-03-18T15:04:00.003+04:002013-03-18T15:04:35.238+04:00вышел Oracle Instant client 32/64 для Mac Os x<div dir="ltr" style="text-align: left;" trbidi="on">
Внезапно.<br />
<br />
<div style="text-align: left;">
<a href="https://blogs.oracle.com/opal/entry/os_x_users_11gr2_oracle" target="_blank">OS X Users! 11gR2 Oracle Instant Client 32 & 64-bit is now available</a>!</div>
<div>
<br /></div>
<div>
Как я говорил, прошлая (10.2.0) 64-битная версия клиента на Маке не работала. Будем посмотреть, что сейчас. Забрать можно отсюда <a href="http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html?msgid=3-8020521751">http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html?msgid=3-8020521751</a></div>
</div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-56244682281031490432013-02-13T00:02:00.000+04:002013-02-13T22:28:53.536+04:00cx_Oracle на Mac OS X - только 32-битная версия.<div dir="ltr" style="text-align: left;" trbidi="on">
Всегда задавался вопросом - если Стив Джобс и Ларри Элиссон по жизни были такими дружбанами, почему на Маке с поддержкой Oracle database так плохо? Или дружба-дружбой,<br />
а бизнес есть бизнес?<br />
Нет, не то, чтобы совсем ужасно. Это я так, бурчу. Тот же <a href="http://download.oracle.com/otn/java/sqldeveloper/sqldeveloper-3.2.20.09.87-macosx.tar.gz" target="_blank">SQL Developer</a> без проблем работает, а для серьезных пацанов есть <a href="http://www.navicat.com/en/products/navicat_oracle/oracle_overview.html" target="_blank">Navicat Oracle</a>, в котором, может быть, не так хорошо кодить PL/SQL, но работать с данными легко и приятно.<br />
<br />
Теперь о плохом. Последнюю версию полного клиента Oracle давно отовсюду убрали, еле нашел на одном торренте. Последняя версия instant client 10.2 для Mac OS X для 64-разрядной системы на оффсайте битая (!), поэтому качайте 32-битную. Далее как обычно - установка, экспорт переменных.<br />
<br />
Теперь об cx_Oracle. По умолчанию он ставит 64-битную версию cx_Oracle, что приводит к ошибке:<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">>>> import cx_Oracle<br />Traceback (most recent call last):<br /> File "<stdin>", line 1, in <module><br />ImportError: dlopen(/Users/user/sites/env/prj1/lib/python2.7/site-packages/cx_Oracle.so, 2): no suitable image found. Did find:<br /><span class="Apple-tab-span" style="white-space: pre;"> </span>/Users/user/sites/env/prj1/lib/python2.7/site-packages/cx_Oracle.so: mach-o, but wrong architecture</module></stdin></span></blockquote>
<br />
Я попробовал несколько вариантов, самый беспроблемный выглядит так:<br />
Идем в <span style="background-color: #eeeeee; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: x-small; line-height: 18px;">$WORKON_HOME/*name_of_virtualenv*/bin</span><br />
<br />
<pre class="lang-py prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><code style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin: 0px; padding: 0px; vertical-align: baseline;"><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">%</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> mv python python</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">fat
</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">%</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> lipo python</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">.</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">fat </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">-</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">remove x86_64 </span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">-</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">output python</span></code></pre>
<pre class="lang-py prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;">после этого активируем виртуалку и ставим cx_Oracle:</pre>
<pre class="lang-py prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">% ARCHFLAGS</span><span class="pun" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">=</span><span class="str" style="background-color: transparent; border: 0px; color: maroon; margin: 0px; padding: 0px; vertical-align: baseline;">"-arch i386"</span><span class="pln" style="background-color: transparent; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"> pip install cx_Oracle</span></pre>
<pre class="lang-py prettyprint prettyprinted" style="background-color: #eeeeee; border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; font-size: 14px; line-height: 18px; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;"><pre class="lang-py prettyprint prettyprinted" style="border: 0px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif; margin-bottom: 10px; max-height: 600px; overflow: auto; padding: 5px; vertical-align: baseline; width: auto; word-wrap: normal;">Источник: http://stackoverflow.com/questions/8169946/cant-get-cx-oracle-to-work-with-python-version-2-7-mac-os-10-7-2-lion-mis</pre>
</pre>
<br />
</div>
EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-25272840339517833532012-04-07T17:22:00.001+04:002012-04-07T17:22:09.289+04:00Обновление Oracle Grid для HP UX Itanium 64<a href="http://surachartopun.com/2011/06/learn-patch-12311357-112022-gi-psu.html">Surachart Opun's Blog: Learn: Patch 12311357 - 11.2.0.2.2 GI PSU</a>: <br />
<br />
<a href="https://chrome.google.com/webstore/detail/pengoopmcjnbflcjbmoeodbmoflcgjlk" style="font-size: 13px;">'via Blog this'</a>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-49498029869208439082012-03-01T18:33:00.000+04:002012-03-01T18:33:01.971+04:00Python cx_Oracle 5.0 New Features Overview<a href="http://www.oracle.com/technetwork/articles/tuininga-cx-oracle-084866.html">Python cx_Oracle 5.0 New Features Overview</a><br /><br />Странно, что эта статья мне раньше на глаза не попадалась.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-83745550264305763972012-02-18T21:21:00.004+04:002012-02-18T23:00:08.592+04:00Рабочий день или выходной? Проверка для ежедневных задач.<div dir="ltr" style="text-align: left;" trbidi="on">
Как узнать, выходной или рабочий сегодня день? C учетом праздников и переносов? Давно хотел написать простенький он-лайн сервис, да руки не доходили. На Новый год немножко лажанул - забыл отключить рассылку прайс-листов у клиента и все праздники спамил клиентские ящики. После этого в спешном порядке на <a href="http://appengine.google.com/" target="_blank">App Engine</a> накатал нужный скриптик. Использовать такие мощности для двух запросов в сутки как-то некошерно, поэтому делюсь - <a href="http://checkworkday.appspot.com/" target="_blank">СнескWorkDay</a>. Просто чекаете адрес <a href="http://checkworkday.appspot.com/check">http://checkworkday.appspot.com/check</a> ; в ответ 0 - выходной, 1- рабочий. Естественно - Россия, естественно - часовой пояс дефолт сити.<br />
<br />
По использованию - вряд ли мои немногочисленные читатели смогут выбрать дневную квоту :-) , но теоретически такой риск есть. Если нужен сервис для серьезного продакшена - пишите, есть платный аккаунт с гарантированным откликом.<br />
По функционалу - лично меня он устраивает в нынешнем виде, но на всякий на днях добавлю поддержку проверки любого дня текущего года + часовые пояса. Если есть мысли об улучшении - пишите.<br />
По поддержке - 5 ближайших лет(2017) гарантированно, далее - при наличии мотивации :-)<br />
Enjoy. </div>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com1tag:blogger.com,1999:blog-20568873.post-52061190545805622112012-02-15T10:16:00.001+04:002012-02-20T09:57:54.476+04:00django-mailer-2 vs django-mailer<div dir="ltr" style="text-align: left;" trbidi="on">
В свое время подыскивая модуль асинхронной отправки почты стал использовать стандартный для таких ситуаций django-mailer. Словил в свое время кучу различных багов из-за несовместимости функций старых и новых функций (были ошибки в формировании адреса отправителя при администраторской рассылке более, чем одному человеку, проблемы с формированием html-писем и прочее ). Стал искать замену и там же на github нашел форк <a href="https://github.com/SmileyChris/django-mailer-2" target="_blank">django-mailer-2</a>. В чем фишка этого модуля? А в том, что используются функции стандартного модуля, но письма при этом валятся в очередь. То есть, старые проекты со стандартными send_mail, mail_admins, mail_managers переедут прозрачно - меняете только импорт. Кроме того, ни одного бага за полгода активного использования. Из серии "поставил и забыл".<br />
Must have.<br />
P.S. На выходных поигрался с <a href="http://habrahabr.ru/company/biggo/blog/102742/#habracut" target="_blank">Celery</a> и теперь думаю, что для больших проектов лучше использовать этот модуль для асинхронных/периодических задач. Если же нужно только отправлять асинхронно почту - django-mailer2 вам в помощь.</div>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-23210719390445364952012-01-28T16:43:00.000+04:002012-01-28T16:43:33.706+04:00Google App Engine и Ubuntu 11.11 - установка python 2.5<div dir="ltr" style="text-align: left;" trbidi="on">
Факт первый - Google App Engine требуется Python 2.5.<br />
Факт второй - в Ubuntu c 11.04 (если не ошибаюсь) Python 2.5 исключен из репозитария.<br />
Я нашел несколько решений, выкладываю самое простое:<br />
<i><b>sudo add-apt-repository ppa:fkrull/deadsnakes</b></i><br />
<i><b>sudo apt-get update && sudo apt-get install python2.5</b></i>
<br />Всё, питон 25 установлен, при этом основным остается 2.7. Для вызова используйте:<br />
<i><b>python2.5</b></i>
</div>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-18307257758981756812011-06-22T16:25:00.000+04:002011-06-22T16:25:05.131+04:00OpenOffice + Python, pабота с файлами MS Word - Блог Романа Ворушина<a href="http://vorushin.ru/blog/58-openoffice-python-ms-word/">OpenOffice + Python, pабота с файлами MS Word - Блог Романа Ворушина</a>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-77276794696346756632011-06-22T16:19:00.000+04:002011-06-22T16:19:56.077+04:00Ограничиваем интерфейс редактирования с помощью прокси-моделей / Django Framework / Хабрахабр<a href="http://habrahabr.ru/blogs/django/120566/">Ограничиваем интерфейс редактирования с помощью прокси-моделей / Django Framework / Хабрахабр</a>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-8315170013836299162011-05-11T09:59:00.000+04:002011-05-11T09:59:21.226+04:00Ubuntu 11.04 и cx_OracleОбновил сервер до Ubuntu 11.04 - отвалился cx_Oracle. Фокус с easy_install (pip) не сработал. Пришлось совершить несколько телодвижений:<br />
1. Качаем с sourceforge.net нужную версию rpm для CentOs - для 11.04 это будет python 2.7 oracle 10<br />
2. пакет "Чужой" сконвертит rpm в deb> sudo alien -d cx_Oracle-5.1-10g-py27-1.i386.rpm<br />
3. Ставим - > sudo dpkg -i cx-oracle_5.1-2_i386.deb<br />
4. PROFIT? А вот и нет. Python наш модуль не видит. Посему либо поправьте PYTHONPATH, либо совершите дополнительные телодвижения:<br />
cd /usr/lib/python2.7<br />
sudo mv site-packages/cx_Oracle* dist-packages/<br />
sudo rmdir site-packages/<br />
sudo ln -s dist-packages site-packages<br />
Вот теперь всё работает. Enjoy!EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-63207485251373437762011-04-24T12:36:00.000+04:002011-04-24T12:36:24.334+04:00Нижняя Волга, рыбалка<a href='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWStzwtrFo1EEQmF1i_732La-aFs_Nk9hnbCBP4K3ifgWZ2pR9YaFZIsF_d2eSz_1Ktwh18AcnoT8SZuqEcMd61tevv3GZf0mKxHTNDXWEdQFDUE_xtvrQHUI6mQusNEUMhw/s1600/DSC00282.JPG'><img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWStzwtrFo1EEQmF1i_732La-aFs_Nk9hnbCBP4K3ifgWZ2pR9YaFZIsF_d2eSz_1Ktwh18AcnoT8SZuqEcMd61tevv3GZf0mKxHTNDXWEdQFDUE_xtvrQHUI6mQusNEUMhw/s320/DSC00282.JPG' border='0' alt=''style='clear:both;float:left; margin:0px 10px 10px 0;' /></a> <div style='clear:both; text-align:LEFT'><a href='http://picasa.google.com/blogger/' target='ext'><img src='http://photos1.blogger.com/pbp.gif' alt='Posted by Picasa' style='border: 0px none ; padding: 0px; background: transparent none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;' align='middle' border='0' /></a></div>EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-48136709790392235642010-12-19T14:09:00.001+03:002010-12-19T14:11:29.778+03:00Муксун на строганину к Новому Году.<a href='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxyyea2NmUXV4pSdfxCd43M1O-zVz8VKrYt0BQ0UwPet2-k5kYqZ3vXHwodWbNuzme3K3-Y_eQO8ZKjHtLRNpnzKbNv-FrceZ8N-NFMBBV4D7OkMP07BRXjjnMZAYu6_ZUww/s1600/DSC_8600.JPG'><img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxyyea2NmUXV4pSdfxCd43M1O-zVz8VKrYt0BQ0UwPet2-k5kYqZ3vXHwodWbNuzme3K3-Y_eQO8ZKjHtLRNpnzKbNv-FrceZ8N-NFMBBV4D7OkMP07BRXjjnMZAYu6_ZUww/s320/DSC_8600.JPG' border='0' alt=''style='clear:both;float:left; margin:0px 10px 10px 0;' /></a> <div style='clear:both; text-align:LEFT'><a href='http://picasa.google.com/blogger/' target='ext'><img src='http://photos1.blogger.com/pbp.gif' alt='Posted by Picasa' style='border: 0px none ; padding: 0px; background: transparent none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;' align='middle' border='0' /></a></div>Вот разжился - друзья из Тикси передали.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-78795188825314042632010-12-13T21:05:00.000+03:002010-12-13T21:05:25.325+03:00DJANGO и ORACLE VIEWSЯ использую связку DJANGO + ORACLE. Как известно, эта связка из стандартных бэкендов наименее проработана. Например, проблема с TRUNC DATE - адепты PostgreSQL передают туда 'hour', а для Oracle нужно 'HH24'. И таких мелких проблем очень много. К счастью, все эти проблемы решаемы, иногда даже без хаков db backenda django. <br />
Итак, ситуация. Пишу B2B приложение, две базы Oracle связаны по dblinkу, одна корпоративная, где ведется учет и вторая специально под сайт. Чтобы не заниматься репликацией между базами было решено сделать несколько представлений на стороне web-базы. Для удобства я решил подложить под них модели, но столкнулся с проблемой syncdb - Oracle вполне ожидаемо не смог создать таблицы (которые по сути были не нужны), потому как имена были уже заняты соответствующими представлениями. Вопрос - как заставить django при синхронизации просматривать не только список таблиц, но также и список представлений?<br />
Первое решение в лоб - как известно, django при проверке таблиц под моделями использует список таблиц из команды inspectdb соответствующего db backenda. В файле django/db/backends/oracle/introspection.py есть функция get_table_list, которая выполняет вот такой запрос: <blockquote><b>SELECT TABLE_NAME FROM USER_TABLES</b></blockquote>. Первым побуждением было просто перебить этот запрос, но тогда при обновлении версии django надо будет опять править этот файл, а память у меня плохая, да и подход у меня другой: сделал и забыл.<br />
Второе решение - обманем django со стороны базы.<br />
Создадим простое представление:<br />
<blockquote><b><br />
create or replace view user_tables as <br />
select a.object_name as table_name<br />
from user_objects a<br />
where a.object_type in ('TABLE'<br />
, 'VIEW')<br />
/</b><br />
</blockquote>Теперь django при синхронизации моделей будет просматривать объединенный список из таблиц и представлений.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-28990466441256256782010-08-26T17:34:00.000+04:002010-08-26T17:34:40.125+04:00Django + Oracle + Aptana = Oracle Enterprise Pack for Eclipse.При проектировании из Aptana мне не хватало нормальной тулзы для связи с базой данных Oracle. Запускать родной Oracle SQL Developer - это значит положить слабый офисный комп, два Java-приложения (+ корпоративный Lotus, который теперь тоже на основе Eclipse) мигом выедают всю оперативную память и лезут в своп. PL/SQL Developer и TOAD сами по себе монстры, но криво работают с Юникодом. <br />
Первый опыт с установкой <a href="http://eclipsesql.sourceforge.net/" target="_blank">SQL Explorer</a> следует признать неудачным, плагин ронял Aptana при попытке просмотреть таблицы схемы.<br />
Нынче с помощью MarketPlace (спасибо <a href="http://vermus.blogspot.com/">Vermusу</a> за наводку на столь полезный плагин) поставил <a href="http://www.oracle.com/technetwork/developer-tools/eclipse/downloads/index.html?ssSourceSiteId=ocomen">Oracle Enterprise Pack</a> - оказалось то, что нужно. Просмотр данных, запросы, планы выполнения - всё есть. Правда, опять пришлось <a href="http://oradir.blogspot.com/2010/05/aptana-sql-editor.html">добавлять параметры запуска</a> - без этого не работает.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-73063943503515807702010-08-20T14:51:00.001+04:002010-08-20T14:54:10.515+04:00Обновил Aptana до 3 BetaНу что сказать - с позиции Python-разработчика стало намного лучше. Во-первых, вторая версия в последнее время у меня вылетала на Java Heap Space. Во-вторых, тормозила нещадно. Третья бета просто летает. Убрано много лишнего, появилась возможность обновить PyDev - теперь с поддержкой Django-шаблонов (ставить с зеркала Nightly builds). Будем смотреть дальше.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com3tag:blogger.com,1999:blog-20568873.post-82403509478660311322010-07-02T12:54:00.001+04:002010-07-02T12:55:11.284+04:00На заметку - ошибка \ufeffИтак - ест исходник на Python / Django, есть Eclipse / Aptana с PyDev. Периодически на первой строчке вижу ошибку, которая, в принципе, ни на что не влияет, но напрягает, потому как из-за неё не видно Outlines. Выглядит это так :<br />
Lexical error at line 1, column 1. Encountered: "\ufeff" (65279), after : "" widgets.py /myproject/mymodule line 0 Problem<br />
<br />
Сегодня попытался понять - что же это такое, оказалось, что во всём виноват первый байт файла - U+FEFF (неразрывный пробел с нулевой шириной), известный также как BOM (byte order mark, метка порядка байтов). Это несуществующий символ, используемый для того, чтобы отличать различные представления unicode. <br />
Я просто удалил этот символ и ошибки исчезли. Кому лень писать скрипт - выбирайте кодировку UTF-8 без BOM.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com6tag:blogger.com,1999:blog-20568873.post-2030638331223496812010-06-08T19:35:00.002+04:002010-06-08T19:52:25.816+04:00Заметка на полях - custom sql в Django.Задача - при развертывании схемы Django на базу создавать триггер на таблицу. Пошел по стандартному пути - создал в директории приложения папку sql, положил туда файл <i>имя_модели</i>.sql Выполняю manage.py syncdb - ошибка <b>ORA-0900</b>, ругается на неправильный код. При выполнении того же кода в sqlplus - никаких ошибок. Посмотрел через sqlcustom - код вменяемый. Напрягло только наличие пустых строк в коде, а этого тот же sqlplus не переносит. Убрал все переводы строк - текст триггера стал выглядеть отвратно, но теперь он выполняется. Бинго! <br />
Вывод - при создании хранимых процедур, функций и пакетов проверяйте скрипты через sqlcustom - вывод <b>не должен содержать пустых строк</b>.<br />
<br />
Нашел также еще один баг - в скрипте создания триггера джанго вырезал последний символ <blockquote>;</blockquote>Простановка в конце пробелов не помогла, поставил костыль - еще одну точку с запятой. Пока помогло, но чувствую, что нужно набросать свой скрипт развертывания.EKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0tag:blogger.com,1999:blog-20568873.post-47283392805865080122010-05-22T12:42:00.001+04:002010-05-22T12:57:48.356+04:00Aptana и Mylyn Trac ConnectorТак как все проекты держу на http://assembla.com, захотелось сделать интеграцию задач с её Trac. Но при попытке поставить Mylyn Trac Connector получил стандартную ошибку несовместимости. Нужно добавить репозитарий:<br />
Help -> Install New Software...<br />
<br />
Add this update site: http://download.eclipse.org/tools/mylyn/update/weekly/e3.4<br />
<br />
и ставить всё оттуда, тогда проблем не будет.<br />
<br />
P.S. Оказывается, в Aptana можно добавить поддержку "родных" tickets из Assembla. Соответствующий коннектор и инструкции по установке можно найти здесь - http://www.assembla.com/wiki/show/assemblamylyn/How_To_UseEKryukovhttp://www.blogger.com/profile/14690339356096144833noreply@blogger.com0