인천 신포동 오래된 대폿집. 다복집.

입구-'신포동 다복집'

입구-'신포동 다복집'

자주 지나다니는 거리에 있는 오래된 대폿집입니다.
저보다 나이가 많은 가게에요.
편안한 분위기에 가격도 착해서 가볍게 막걸리 한잔 걸치기 좋은 곳이죠.
단 밤 열 시 좀 넘으면 문을 닫기 때문에 너무 늦게 가면 안 돼요.

막걸리-'신포동 다복집'

새우 튀김-'신포동 다복집'

뭘 먹을까 고민하다 막걸리와 새우 튀김을 주문했어요.
일식집 튀김 방식이 아닌 분식집 방식 튀김인데 맛은 썩 괜찮습니다.
그리고 기본으로 나오는 김치와 동치미가 제대로 맛있어요.
앞으로도 한잔 걸치러 종종 찾아야겠습니다.
이런 대폿집이 집 가까이 있어서 참 좋네요. :D



크게 보기



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

로드리게스. 멋진 가수 아저씨 이야기.

이 영화를 보기 전까진 로드리게스가 누군지도 몰랐습니다.
이 아저씨 노래 좋아요.
미국 디트로이트 출신 로드리게스는 2집 앨범까지 냈지만 흥행하지 못했답니다.
그런데 바다 건너편 남아프리카 공화국에선 엄청나게 인기가 좋았다네요.
20세기 말까지 인종차별이 심했던 꽉 막힌 남아프리카 공화국.
솔직한 로드리게스의 가사가 남아공 국민들 심금을 울렸나 봅니다.

난 궁금해 네가 얼마나 오랜 시간을 살았는지.
난 궁금해 또 얼마나 많은 계획을 망쳤는지.
난 궁금해 넌 얼마나 많은 섹스를 해 봤는지.
난 궁금해 다음 차례는 누군지.
난 궁금해 궁금해 완전 궁금해.

이런 가사였죠.
로드리게스 노래는 남아공 검열에 걸려서 앨범 속 거의 모든 곡이 방송 불가 판정을 받았었다고 해요.

아무튼, 남아공에서 인기 좋은 가수.
로드리게스 아저씨는 막노동하며 생계를 이어갑니다.
“남아공에서 인기 있다는 걸 미리 알았다면 삶이 달라졌을 텐데 아쉽지 않으세요?”
“음. 글쎄요. 어쩜 달라졌을 수도 있겠네요.”
로드리게스라는 아저씨 멋집니다.
지난 일에 아쉬움 없는 그 말투엔 초연함이 어나더군요.

American Zero, South African Hero
미국에선 꽝, 남아공에선 영웅.

이 문구를 보고 이런 생각이 들었습니다.
이 세상엔 엉뚱한 자리에서 꽝이나 마이너스 삶을 사는 사람이 얼마나 많을까요?
에너지를 쏟을 곳을 찾지 못해 헛된 곳에 힘쓰는 사람들 말이에요.
누구든 가슴 뛰는 곳에 열정을 쏟을 기회가 많아지면 좋겠습니다.

무언가를 거머쥘 능력을 갖춘 사람은 대단한 사람입니다.
세상에 몇 안 되는 사람만이 자기 분야에서 위업을 이루지요.
그리고 손에 무엇이 쥐어지든 연연하지 않는 사람은 위대한 사람입니다.

로드리게스 아저씨는 위대한 예술가 같아요.


슈가맨(Sugar man)

난 궁금해(I wonder)



by


Tags : , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

국립중앙박물관. 이슬람의 보물 - 알 사바 왕실 컬렉션.

인도 왕궁 정원-'이슬람의 보물 - 알 사바 왕실 컬렉션전'

무슨 전시가 있는지도 모르고, 계획 없이 국립 중앙박물관에 갔습니다.
주말이고 날씨도 화창한 게 기분이 좋더라고요.
‘요즘엔 무슨 전시를 하나~?’
매표소에 가니 ‘이슬람의 보물 - 알 사바 왕실 컬렉션’이 기획전이 열리고 있네요.
그릇, 의복, 카펫, 장신구, 관, 건축물, 책 등 다양한 수집품들이 전시되어 있어요.

메카 방향과 거리를 알려주는 지도.-'이슬람의 보물 - 알 사바 왕실 컬렉션전'
메카까지 방향과 거리를 정확하게 알려준다는 지도.

이런 신기한 물건이 가득해요.

그 중 가장 눈길을 잡아끄는 건 보석으로 화려하게 장식된 각종 장신구였습니다.
반지, 귀고리, 팔찌 등등 많았는데요.
손잡이가 화려한 단검이 멋지더군요.
사진은 찍지 못했지만, 앞면과 뒷면을 다른 방식으로 장식한 게 인상적이었어요.

궁수용 반지 -'이슬람의 보물 - 알 사바 왕실 컬렉션전'

궁수용 반지는 한국에서 활 쏠 때 쓰는 깍지랑 비슷하게 생겼어요.
다만 보석으로 장식되어 화려했습니다.

카타르-'이슬람의 보물 - 알 사바 왕실 컬렉션전'

아! 그리고 게임에서나 보던 카타르라는 무기도 실제로 봤네요.
태어나서 지금까지 박물관 다니면서 카타르는 처음 봤습니다.
이렇게 전시품이 다양하니 와볼 만하다 싶어요.

또 이 전시회에서 마음에 든 건 아랍어 글씨체에 대한 설명이었어요.
사실 아랍어는 봐도 이게 글씬지 그림인지도 분간이 잘 안 가는 판에,
글씨체까지 알아차리는 건 쉽지 않지요.
근데 설명을 잘해놨더라고요.
꼭 한국어 돋움체, 바탕체, 필기체 같아요.
아무튼, 즐거운 관람이었습니다.

이슬람의 보물 -알 사바 왕실 컬렉션은,
이촌역 국립중앙박물관에서 2013.10.20.까지 전시합니다.

아라베스크-'이슬람의 보물 - 알 사바 왕실 컬렉션전'

이슬람의 보물 - 알 사바 왕실 컬렉션 전시에서 재미있게 본 것.


아랍 글씨체 세 가지 기본 유형

  • 무디와르체 : 원형
  • 무살라스체 : 삼각형
  • 티임체 : 원형과 삼각형의 복합형태

자주 쓰이는 글씨체

  • 쿠파체 : 직선적이고 모난 형태.
  • 나스흐체 : 전반적으로 둥글고 우아한 필기체.
  • 솔루스체 : 초기 쿠파체를 보완한 곡선과 경사진 선 모양의 서체로 1/3을 뜻하며 모스크 장식 등 건축에 널리 사용된다. 세로획이 가로획보다 세 배가 긴 것이 특징.

그 밖에 재미있게 본 것

  • 모스크 기도실 바닥을 덮는 카펫을 사프(saff)라고 한다.
  • 인도 여름 카펫은 면에 비단으로 수놓았다.
  • 타구는 가래나 침을 뱉는 용도로 쓰는 그릇이다.
  • 아라베스크는 양식화된 식물 모티브와 줄기 등을 뜻하는 르네상스 시대 이탈리아어 아라베스코(a rabesco)에서 유래하였다. (아랍에서 유래 한 것이 아님.)

이슬람의 보물 - 알 사바 왕실 컬렉션 웹사이트



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

Canjs와 Flask를 이용한 웹개발 예제

클라이언트 사이드 자바스크립트 프레임워크인 Canjs와
파이썬 마이크로 프레임워크인 Flask를 이용한 웹 어플리케이션 예제입니다.
이 Canjs + Flask 예제가 프레임워크 이해에 도움이 되길 바랍니다.


Canjs + Flask 예제 소스


예제에 사용된 라이브러리

  • Canjs, 클라이언트 사이드 자바스크립트 프레임워크.
  • RequireJS, 자바스크립트 파일•모듈 로더.
  • Initializr, HTML5 템플릿.
  • Bootstrap, 프론트엔드 프레임워크.
  • JSDoc, 자바스크립트 문서화 도구.
  • BusterJS, 자바스크립트 테스팅 도구.
  • mustache, 템플릿 엔진.
  • i18next, 자바스크립트 다국어 도구.
  • Flask, 가벼운 파이썬 프레임워크.
  • Flask-SQLAlchemy, SQLAlchemy의 플라스크 플러그인.
  • Jade(pyjade), 파이썬용 Jade 템플릿 엔진 플러그인.
  • Flask-Babel, 플라스크용 다국어 플러그인.

예제의 이해를 돕는 글



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

잘 짜여진 자바스크립트 MVC 프레임워크. Canjs

Backbone, AngularJS, Spine….
그동안 나왔던 자바스크립트 프레임워크를 조금씩 건드려는 보았지만,
항상 아쉬움이 남았습니다.
이번에 Canjs를 써보니, 정말 잘 만들어진 프레임워크라는 생각이 들어요.
자바스크립트MVC 프레임워크를 써 볼까 생각 중이시라면, Canjs 한번 고려해 보세요.

can.Control

컨트롤러에서 이벤트 처리

"li .destroy {Event.destroy}": function( el, event) {
var todo = el.closet('li').data('todo);
todo.destroy();
event.stopPropagation();}
});
Events = {destroy : "click"};

css Selector, html.getElementBy, $(selector)가 Control의 셀렉터로 사용된다.

When the element your Control is bound to is removed from the DOM,
the Control destroys itself, cleaning up any bound event handlers.

can.Control 이 아는 이벤트.
* change
* click
* contextmenu
* dblclick
* focusin
* focusout
* keydown
* keyup
* keypress
* mousedown
* mouseenter
* mouseleave
* mousemove
* mouseout
* mouseover
* mouseup
* reset
* resize
* scroll
* select
* submit

링크 처리 방법(How can I make a link in Canjs?)

레이어(layer)
<a id="id" href="javascript://">href</a>

페이지(page)
<a id="id" href="#!id">href</a>

무스타치에서 콜백 받기(Mustache Element Callback)

{{data 'model'}}

경로 설정(RequireJS Paths)

requireJS can require is /can
requireJS에서 canJS를 쓸 땐 can.js를 패스로 잡고 사용해야 한다.
registerHelper이용을 위해서는 can/view/mustache가 필요하다.

404루트 잡기(How to define a catch all route to handle 404 in can js?)

http://stackoverflow.com/questions/13824665/how-to-define-a-catch-all-route-to-handle-404-in-can-js

can.route.bind('change', function(ev, newVal) {
if (newVal === 'route') {
var valid = false;
$.each(can.route.routes, function(k,v) {
if (new RegExp(v.test).test(window.location.hash)){
valid = true;
return; //exit loop
}
})
if (!valid) {
//handle the false route here
}
}
});

다국어 지원(Localization)

Localization is a good example of a custom helper you might implement in your application. The below example takes a given key and returns the localized value using jQuery Globalize.

1. Mustache.registerHelper('l10n', function(str, options){
2. return Globalize != undefined
3. ? Globalize.localize(str)
4. : str;
5. });

can.route에서 i18next 데이터를 받아오지 못할 때

can.when을 이용하여 초기화가 된 후 can라우팅 처리를 해 준다.


var lang =utils.getParam('lang');
var i18noption = {debug: true};
lang != undefined
? i18n
option.lng = lang
: i18n_option.lng = "en";
can.when(i18n.init(i18n_option)).then(function (){});

모델 관계(model associations)

https://forum.javascriptmvc.com/topic/questions-about-model-associations

<div class="header">
<h1>Association</h1>
</div>
<!-- YOUR CODE HERE -->
<div id="contacts"></div>

can.fixture("/contacts.json", function(){
return [{
'id': 1,
'name' : 'Justin Meyer',
'birthday': '1982-10-20',
tasks : [{
id: 1,
title: "write up model layer",
due: "2010-10-5"
}]},{
'id': 2,
'name' : 'Brian Moschel',
'birthday': '1983-11-10',
tasks : [{
id: 2,
title: "write up funcunit",
due: "2009-5-1"
},{
id: 3,
title: "test funcunit",
due: "2010-3-15"}]
},{
'id': 3,
'name' : 'Bobby Joe',
'birthday': '1980-2-10'
}];
})

can.Model.convert.date = function(raw){
if(typeof raw == 'string'){
var matches = raw.match(/(\d+)-(\d+)-(\d+)/);
return new Date( +matches[1],
(+matches[2])-1,
+matches[3] );
}else if(raw instanceof Date){
return raw;
}
};

// A task model that has a date
can.Model("Task",{
attributes : {
due : 'date',
}
},{
weeksPastDue : function(){
return Math.round( (new Date() - this.due) /
(1000*60*60*24*7 ) );
}
});

// A contact model that has many tasks
can.Model("Contact",{
attributes : {
birthday : 'date',
tasks: "Task.models"
},
findAll : "/contacts.json"
},{
ageThisYear : function(){
return new Date().getFullYear() -
this.birthday.getFullYear()
},
getBirthday : function(){
return ""+this.birthday.getFullYear()+
"-"+(this.birthday.getMonth()+1)+
"-"+this.birthday.getDate();
}
});

// Get all contacts and put them on the page
Contact.findAll({},function(contacts){
var contactsEl = can.$('#contacts');

can.each(contacts, function(contact){
var li = can.$('<li>')
.html(contact.name + " "+ contact.ageThisYear())
.appendTo(contactsEl);

var ul = can.$("<ul>");
var tasks = contact.attr('tasks')

if(tasks){
tasks.each(function(){
this.attr('contact', contact);
ul.append('<li>'+this.title+" "
+this.weeksPastDue()+' contact: '+ this.attr('contact.name') +'</li>')
});
}

ul.appendTo(li)
});
});

 

Canjs 웹사이트



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

Javascript 모듈 관리엔 RequireJS

자바스크립트 모듈이 많아 관리가 어렵다면, RequireJS를 사용 해 보세요.

설정(Configuration)


require.config({
"baseUrl": "/static/js/vendor",
"paths": {
"app": "../app",
"bootstrap": [
'//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min',
"bootstrap"
],
"jquery": [
"//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min",
"jquery-1.9.1.min"
],
"can": "can",
shim: {
"bootstrap": {
deps: ["jquery"],
exports: "$.fn.popover"
},
enforceDefine: true
}
}
});

모듈 정의(define function)


define(["jquery"],function($){
return {
getParam: function(paramname){
var value = new RegExp('[\?&]' + param
name + '=([^&#]*)').exec(window.location.href);
return value[1];
},
test: function(text){
console.log("test : "+text);
}
};
});

두 모듈을 한 파일에 넣는 방법(requirejs, two classes in one file)

http://stackoverflow.com/questions/9806940/requirejs-two-classes-in-one-file

define('test', ['jquery'], function() {
var exports = {};
exports.test1 = {
method1 : function () {
console.log("test1 - method 1");
},
method2 : function () {
console.log("test1 - method 2");
}
};
exports.test2 = {
method1 : function () {
console.log("test2 - method 1");
},
method2 : function () {
console.log("test2 - method 2");
}
};

return exports;
});

그리고 아래처럼 사용하면 된다.
require(['test'], function (test) {
var test1 = test.test1;
});

두 모듈을 한 파일에 넣는 다른 방법
http://blog.credera.com/topic/technology-solutions/java/modular-javascript-with-requirejs


define(['json!data/customers'], function(customers){
var getRow = function(id) {
return customers[id];
};

var getAll = function() {
return customers;
};

var update = function(data) {
// do something cool with the data
};
return {
get: getRow,
list: getAll,
update: update
};
});


오류 해결

  • Jquery CDN경로가 올바르지 못할 경우 Bootstrap로딩에 오류가 난다.
  • 같은 모듈(예: bootstrap)이 중복 로드될 경우 충돌이 일어난다.

RequireJS 홈페이지



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

유용한 javascript 예제와 팁

URL 파라메터 받아오기(get PARAM)

http://www.codetreat.com/get-url-parameters-values-with-javascript

$.params = function(paramname){
var value = new RegExp('[\?&]' + param
name + '=([^&#]*)').exec(window.location.href);
return value[1];
}

Jquery 셀렉터 성능(JQUERY SELECTOR Performance)

http://jsperf.com/selectors-perf/6
cssSelector는 id 나 element와 함께 쓰지 않고 단독으로 사용한다.


var obj = document.getElementById("childDiv");
xxx = obj.getElementsByClassName("txtClass");

 

이벤트 처리

preventDefault() : 이벤트의 기본 행동을 막는다.
If this method is called, the default action of the event will not be triggered.
stopPropagation() : 상위 핸들러로 이벤트를 넘기지 않도록 막는다.
Prevents the event from bubbling up the DOM tree,
preventing any parent handlers from being notified of the event.

prepend() - 앞쪽에 내용을 붙인다.(to attach content as a prefix.)
append() - 뒷쪽에 내용을 붙인다. (to attach content as a suffix.)

배열 요소에서 데이터를 받고 싶을 땐 $()로 한번 더 감싼다.
$($(array_selector)[0]).data(something);


두번 submit되는 문제(prevent submit twice)
onclick이벤트 보다는 onsubmit 이벤트를 사용한다.
http://stackoverflow.com/questions/2830542/prevent-double-submission-of-forms-in-jquery

this.element.find('.save').attr('disabled','disabled');

// jQuery plugin to prevent double submission of forms
jQuery.fn.preventDoubleSubmission = function() {
$(this).bind('submit',function(e){
var $form = $(this);
if ($form.data('submitted') === true) {
// Previously submitted - don't submit again
e.preventDefault();
} else {
// Mark it so that the next submit can be ignored
$form.data('submitted', true);
}
// Keep chainability
return this;
};


JSON

Object to String
JSON.stringify(obj);
Parse JSON response
JSON.parse(obj);

JSON.parse()사용시 오류 : Uncaught SyntaxError: Unexpected token o
http://stackoverflow.com/questions/8081701/i-keep-getting-uncaught-syntaxerror-unexpected-token-o
데이터형이 올바르지 않아서 나는 오류이다.
Looks like jQuery takes a guess about the datatype.
It does the JSON parsing even though you're not calling getJSON()--
then when you try to call JSON.parse() on an object, you're getting the error.


loglevel

https://github.com/pimterry/loglevel
원하는 레벨의 로그를 콘솔 메시지로 보낸다.
켜고 끄는 것이 편리하다.
log.enableAll() and log.disableAll() methods.
* log.trace(msg)
* log.debug(msg)
* log.info(msg)
* log.warn(msg)
* log.error(msg)


JavaScript 디버깅

chrome dev tool -> Settings -> General -> Disable cache
Timeline을 이용하면 어떤 코드가 어플리케이션에 부하를 주는지 찾아준다.
메모리 누수가 발생한다면 찾아 개선한다.
Profiles도구에서 Heap Snapshot을 두 개 만들어 comparison view로 비교하면 성능 저하 원인을 찾기 편하다.



by


Tags : , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

자바스크립트용 개발 문서 작성기. JSDOC

주석 달기


/** define namespace
* @namespace category
*/

/** use namespace with hash
* @name category#name
* @constructor
*/

/** use member of for constructor
*@memberof category#name
*/


설정(configuration)

remove all comments.
// You must remove the comments before adding these options to your .json file

{
"tags":{
"allowUnknownTags":true
},
"source":{
"include":[],
"exclude":[],
"includePattern":".+\.js(doc)?$",
"excludePattern":"(^|\/|\\)_"
},
"plugins":[],
"templates":{
"cleverLinks":false,
"monospaceLinks":false
},
"opts":{
"template":"default", // same as -t default
"encoding":"utf8", // same as -e utf8
"destination":"./out/", // same as -d ./out/
"recurse":true, // same as -r
"tutorials":"path/to/tutorials",// same as -u path/to/tutorials, default "" (no tutorials)
"query":"value", // same as -q value, default "" (no query)
"private":true, // same as -p
"lenient":true, // same as -l
// these can also be included, though you probably wouldn't bother
// putting these in conf.json rather than the command line as they cause
// JSDoc not to produce documentation.
"version":true, // same as --version or -v
"explain":true, // same as -X
"test":true, // same as -T
"help":true, // same as --help or -h
"verbose":true, // same as --verbose, only relevant to tests.
"match":"value", // same as --match value, only relevant to tests.
"nocolor":true // same as --nocolor, only relevant to tests
}
}


실행
jsdoc -c conf.json

JSDOC github



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

음악 듣는 재미를 찾아준 이어폰. 로지텍 UE900.

작년에 UE Triple.fi 10 pro를 중고로 방출하고, 소니의 이름 모를 이어폰을 사용했습니다.
꽤 만족스러운 이어폰이어서 트리플파이 생각이 별로 안났지요.
헌데 어느날 그 이어폰을 잃어버렸어요.

저가형 번들 이어폰을 써 보았습니다.
G어폰으로 알려진 옵티머스G 용 LG 쿼드비트(QuadBeat)도 써 보고,
대륙의 실수라 불리는 사운드매직 PL30 Plus Pro도 사용해 보았어요.
그런데 영 아쉽습니다.
귀에 이어폰 꼽는 게 전혀 즐겁지 않았어요.
음악은 소음처럼 들리고, 귀도 편하지 않았거든요.
그래서 방출했던 트리플파이를 다시 들여와야겠다고 마음먹었습니다.
그런데 단종되었다네요.
그리고 후속인 UE900이 로지텍에서 나왔습니다.
Ultimate Ears가 로지텍에 합병 되었거든요.
UE는 Ultimate Ears의 약자에요.
트리플파이는 BA 유닛이 3개였는데,
이번에 나온 UE900이란 녀석은 BA 유닛이 4개래요.
거기에다가 착용감도 트파보다 좋다네요.
'아, 이거다!' 싶었지요.
보통 하루 6시간 정도 이어폰을 사용하니,
기왕 쓰는 거 편하고 마음에 드는 녀석을 쓰는 게 좋겠단 들었어요.

comment-'title'

2주일간 숙고해서 산 UE900이 왔습니다.

UE900은 4개의 BA(Balanced Armature) 유닛을 탑재했어요.

우선 BA에 대해 알아보겠습니다.

다이나믹 방식 :
진동판에 코일을 부착하고 이를 자석과 가까이 배치한 코일에 음성신호(교류전기)를 끌여들 코일에 유도된 자력이 자석과 밀고 당기는 힘으로 굴리는 방식
BA 방식 :
BA 무빙코일과의 차이점은 진동판이 코일에 부착되어 움직이는 것이 아니라,
자석과 코일에 인접한 자력으로 말미암 상호반응으로 소리를 낸다는 것입니다.
(자료 출처 : http://skullchristal.tistory.com/137)

다이나믹 방식이 보편적으로 쓰인대요.

UE900의 BA유닛은 아래 역할을 담당합니다.
2개의 BA 유닛 : 저역을 담당
2개의 BA 유닛 : 중역과 고역을 각각 담당


로지텍 UE900 사용기

우선 착용감은 트리플파이보다 좋습니다.
프랑켄슈타인처럼 귀 밖으로 나사가 삐져나오지 않아요.
그러나 UE900음질은 기대에 좀 못미칩니다.
트리플파이만큼 감동이 없어요.
트파엔 뭔가 강렬함이 있었는데 말이죠.
UE900은 비록 트파처럼 야생마 같은 맛은 없지만,
섬세하고 편안합니다.
어찌 되었건 음악 듣는 즐거움을 다시 찾아준 녀석이니까요.
UE900.
이 녀석 정 붙이고 줄 열 번 갈아야 할 때까지 쓰렵니다.



by


Tags : , , , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

파이썬 Flask 플러그인 안내와 팁.

데이터베이스
Flask-SQLAlchemy : OR매핑을 지원하는 플라스크용 파이썬 SQL toolkit
SQLAlchemy에서 상속(Inheritance) : http://docs.sqlalchemy.org/en/rel_0_7/orm/inheritance.html

SQLAlchemy 컬럼에 데이터가 생성될때나 업데이트 될때 현재 시각을 자동으로 넣는 방법.
updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

로그인·보안
Flask-Social : 소셜 네트워크와의 연결을 간편하게 해 줌.
Flask Security(Auth) : 로그인과 권한관리.

관리자 페이지
Flask-Admin : 관리자 페이지를 손쉽게 만들도록 도와줌.

다국어 지원
Flask-Babel : 파이썬용 다국어 지원 Babel의 Flask 플러그인

캐쉬
flask-cache : 캐쉬 설정을 도와줌.

에셋 관리
flask-assets : 각종 static 에셋 관리를 편하게 도와줌.
사용하고자 하는 기능에 따라 추가 모듈이 필요하다. (css 압축, scss사용)
pip install cssmin
pip install pyscss
Flask-Assets extension에서 pyScss컴파일러 사용 설정법

from flask import Flask, render_template
from flask.ext.assets import Environment, Bundle

app = Flask(__name__)

assets = Environment(app)
assets.url = app.static_url_path
scss = Bundle('foo.scss', 'bar.scss', filters='pyscss', output='all.css')
assets.register('scss_all', scss)
And in the template include this:

{% assets "scss_all" %}
{% endassets %}

SCSS file은 debug모드에서도 컴파일 된다.

캐쉬
Flask-Cache : 플라스크에서 캐쉬 사용 하기 쉽게 도와줌.
# Flask-Cache Cache Type
CACHE_TYPE = 'simple' # 개발 시
CACHE_TYPE = 'redis' # 배포 시. redis 서버 구동 필요.
from flask.ext.cache import Cache

app = Flask(__name__)
cache = Cache()
cache.init_app(app, config={'CACHE_TYPE': CACHE_TYPE})

파일 업로드
Flask-Uploads : 파일 업로드 관련 처리를 도와줌.
from flask.ext.uploads import UploadSet
images = UploadSet()
images.__init__('upload', IMAGES)
filename = images.save(files, folder='/images', name='test.')
image_path = images.path(filename)
url = images.url(thumbnail)

텍스트 검색
Flask-WhooshAlchemy : 텍스트 기반 검색을 쉽게 도와줌

오류 추적
flask-exceptional : 오류 추적 서비스인 exceptional를 flask에서 이용 가능하게 도와줌.

전자상거래(e-commerce) [flask용 extension 아님]
stripe : 결제 모듈을 간편하게 시스템에 붙이도록 도와주는 서비스.
satchmoproject : 오픈소스 전자 상점 프레임워크 (satchmo Wiki)
satchless : 프레임워크에 종속적이지 않은 e-commerce용 클래스와 패턴 모음
flamaster : flask용 e-commerce eventing 시스템

Flask에서 JSON 다루기(JSON Handling in Flask)
http://flask.pocoo.org/docs/api/#module-flask.json

import requests
r = requests.get(QUERY_URL)
return r.json
//normal return
return jsonify(username=g.user.username,
email=g.user.email,id=g.user.id)

jsonify a SQLAlchemy result set in Flask
http://stackoverflow.com/questions/7102754/jsonify-a-sqlalchemy-result-set-in-flask
jsonify의 문제는 object가 자동으로 json화 되지 않는다는 것이다.
serialize를 위해 다음을 모델에 추가 해 준다.


def dump_datetime(value):
"""Deserialize datetime object into string form for JSON processing."""
if value is None:
return None
return [value.strftime("%Y-%m-%d"), value.strftime("%H:%M:%S")]

class Foo(db.Model):
//... SQLAlchemy defs here..
def __init__(self, ...):
//self.foo = ...
pass
@property
def serialize(self):
"""Return object data in easily serializeable format"""
return {
'id' : self.id,
'modified_at': dump_datetime(self.modified_at),
# This is an example how to deal with Many2Many relations
'many2many' : self.serialize_many2many
}
@property
def serialize_many2many(self):
"""
Return object's relations in easily serializeable format.
NB! Calls many2many's serialize property.
"""
return [ item.serialize for item in self.many2many]

뷰에서는 아래처럼 사용한다.

return jsonify(json_list=[i.serialize for i in qryresult.all()])

gunicorn서버 사용 설정.

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
app.run()

Blueprint
routing관리에 이용한다.
application/feedback 폴더에 모듈을 넣을 경우.

from flask import Blueprint
mod = Blueprint('root', __name__, url_prefix='') // prefix를 공란으로 두면 root를 의미한다.
mod = Blueprint('feedback', __name__, url_prefix='/feedbacks') // prefix를 채우면 route('/')가 해당 prefix와 같다.
@mod.route('/')

새로운 디렉토리를 만들고 __init__.py파일을 추가해야 import시 인식한다.

모듈을 사용하려면 어플리케이션에서 등록해 준다.

from application.feedback.views import mod as feedbacksModule
app.register_blueprint(feedbacksModule)

파일 여러개 올리기(Uploading multiple files with Flask)
http://stackoverflow.com/questions/11817182/uploading-multiple-files-with-flask


@app.route("/upload", methods=["POST"])
def upload():
uploadedfiles = flask.request.files.getlist("file[]")
print uploadedfiles
return ""

동적으로 생성된 이미지 파일의 url 받기(How to get url for dynamically generated image file?)
http://stackoverflow.com/questions/12034949/flask-how-to-get-url-for-dynamically-generated-image-file

@app.route("/imgs/")
def images(path):
generateimg(path)
fullpath = "./imgs/" + path
resp = flask.makeresponse(open(fullpath).read())
resp.content_type = "image/jpeg"
return resp

mydomain.com/static/test.jpg

from flask import Flask, redirect, url_for

app = Flask(__name__)
@app.route('/')
def index():
generate_img("test.jpg"); #save inside static folder
return '<img src=' + url_for('static',filename='test.jpg') + '>'

Jade
두개의 속성을 지정할 땐 콤마(,)를 잊지 않는다.

script(data-main='js/app', src='js/vendor/require.js')



by


Tags : , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!

최고의 빵집. 신포동 프렌치빌.

입구-'신포동 빵 맛집. 프렌치빌.'


신포동에 맛있는 집 많습니다.
하지만 딱 한 집을 뽑아야 한다면 바로 이 프렌치빌 빵집입니다.
몇 년 전 우연히 들른 뒤로 단골이 되었어요.

프렌치빌 빵 정말 맛있습니다.
식빵도 맛있고 케이크도 맛있고 다 맛있어요.
우선 초콜릿이 들어간 종류는 확실히 맛이 좋아요.
초콜릿 케이크나 초코 빵. 뭐 이런 종류죠.
왜냐면 프렌치빌은 제과점이면서 수제 초콜릿 전문점이기도 하기 때문이에요.
치즈가 들어간 케이크류도 맛이 좋습니다.
프로마쥬, 티라미스, 치즈케이크 다 맛있어요.


프로마쥬-'신포동 빵 맛집. 프렌치빌.'


프랑스 파리에 가면 안젤리나라는 유명한 제과점이 있습니다.
사람들이 한 시간 줄을 서서 몽블랑과 핫초코를 먹는 유명한 빵집이지요.
거기서 몽블랑 먹으면서 프렌치빌 생각이 나더라고요.
‘아. 역시 우리 동네 프렌치빌보다 맛있는 빵집은 없는 건가?’

혹시나 프렌치빌 앞을 그냥 지나칠 일이 생기면 아쉽습니다. :D

동인천에 왔는데, 달달한게 기신다면? 프렌치빌 적극 추천해요.



신포동 맛집. 프렌치빌 위치.

크게 보기



by


Tags : , , , , , , , ,

  • 재미있게 읽으셨나요?
    광고를 클릭해주시면,
    블로그 운영에 큰 도움이 됩니다!