const menu = {

  _courses : {

  _appetizers : [],

  _mains : [],

  _desserts : [],

    set appetizers (appetizer){

      this._appetizers.push(appetizer);

    },

    set mains (main){

      this._mains.push(main);

    },

    set desserts (dessert){

      this._desserts.push(dessert);

    },

    get appetizers(){

      return this._appetizers;

    },

    get mains(){

      return this._mains;

    },

    get desserts(){

      return this._desserts;

    }

  },

  get courses(){

    return {

      appetizers : this._courses.appetizers,

      // 이것은 appetizers getter 메소드를 사용합니다.

      mains : this._courses.mains,

      // 이것은 mains getter 메소드를 사용합니다.

      desserts : this._courses.desserts

      // 이것은 desserts getter 메소드를 사용합니다.

    }

  },

  set courses(course){

    

  },

  addDishToCourse(courseName, dishName, dishPrice){

    const dish = {

      name: dishName,

      price: dishPrice

    };

    //this._courses[courseName].push(dish);

this._courses[courseName]= dish;

  },

  getRandomDishFromCourse(courseName){

  const dishes = this._courses[courseName];

    const randomIndex = Math.floor(Math.random() * dishes.length);

    return dishes[randomIndex];

  },

  generateRandomMeal(){

    const appetizer = this.getRandomDishFromCourse('appetizers');

    const main = this.getRandomDishFromCourse('mains');

    const dessert = this.getRandomDishFromCourse('desserts');

    const totalPrice = appetizer.price + main.price + dessert.price;

    

    return `당신의 식사는 ${appetizer.name}, ${main.name}, ${dessert.name} 입니다. 가격은 ${totalPrice}입니다.`;

  }

};


menu.addDishToCourse('appetizers', '샐러드', 4.25);

menu.addDishToCourse('appetizers', '과일', 1.25);

menu.addDishToCourse('appetizers', '스프', 5.25);

menu.addDishToCourse('mains', '스테이크', 12.25);

menu.addDishToCourse('mains', '파스타', 8.25);

menu.addDishToCourse('mains', '피자', 15.25);

menu.addDishToCourse('desserts', '쿠키', 1.25);

menu.addDishToCourse('desserts', '주스', 2.64);

menu.addDishToCourse('desserts', '커피', 2.64);


let meal = menu.generateRandomMeal();

console.log(meal);

'Coding' 카테고리의 다른 글

scss _presets.scss  (0) 2018.08.22
fabric 참고  (0) 2018.06.21
ES6 ::: 배열  (0) 2018.06.18
선택 안됨 Jquery ::: 반복연습 2번째  (0) 2018.06.12
Jquery ::: 반복연습 1번째  (0) 2018.06.12

배열은 목록이며 JavaScript에 데이터를 저장하는 방법입니다. 배열은 대괄호 []로 만듭니다. 배열의 각 항목은 0부터 시작하는 번호가 매겨진 위치에 있습니다. myArray [0]과 같은 구문으로 번호가 지정된 위치를 사용하여 배열의 한 항목에 액세스 할 수 있습니다. myArray [0] = "new string"과 같은 구문을 사용하여 번호가 지정된 위치를 사용하여 배열의 항목을 변경할 수도 있습니다. 배열에는 길이 속성이있어서 배열에있는 항목 수를 볼 수 있습니다. 배열에는 .push () 및 .pop () 등의 고유 한 메서드가 있습니다.이 메서드는 각각 배열에서 항목을 추가 및 제거합니다. 배열에는 .slice () 및 .shift ()와 같이 다른 기능을 수행하는 다른 많은 메서드가 있습니다.

Mozilla Developer Network 웹 사이트에서 모든 배열 방법에 대한 설명서를 읽을 수 있습니다. 배열을 포함하는 변수는 let 또는 const로 선언 할 수 있습니다.

const로 선언 된 경우에도 배열은 여전히 ​​변경 가능합니다. 그러나 const로 선언 된 변수는 다시 할당 할 수 없습니다.


'Coding' 카테고리의 다른 글

fabric 참고  (0) 2018.06.21
es6 ::: getter & setter  (0) 2018.06.19
선택 안됨 Jquery ::: 반복연습 2번째  (0) 2018.06.12
Jquery ::: 반복연습 1번째  (0) 2018.06.12
ODOO 11 ::: ORM API - Environment  (0) 2018.04.27

Jquery


반복연습 2번째




HTML


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2번째 슬라이드 만들기</title>
<link href="main.css" rel="stylesheet">
</head>
<body>

<div class="slide-block">
<div class="slide">
<div class="item" data-color="#9999FF" data-target="1"></div>
<div class="item" data-color="#FFCCCC" data-target="2"></div>
<div class="item" data-color="#996666" data-target="3"></div>
<div class="item" data-color="#FF9966" data-target="4"></div>
<div class="item" data-color="#6699CC" data-target="5"></div>
</div>
<div class="slide-arrow">
<div class="left">
<i class="fa fa-angle-left" aria-hidden="true"></i>
</div>
<div class="right">
<i class="fa fa-angle-right" aria-hidden="true"></i>
</div>
</div>
<div class="anchor">
<div class="active" data-anchor="1"></div>
<div data-anchor="2"></div>
<div data-anchor="3"></div>
<div data-anchor="4"></div>
<div data-anchor="5"></div>
</div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://use.fontawesome.com/3398c33652.js"></script>
<script src="main.js"></script>
</body>
</html>




CSS


*{
border: 0;
padding: 0;
margin: 0;
}

.slide-block {
width: 700px;
height: 400px;
border: 1px solid #eee;
position: relative;
overflow: hidden;
margin: 10% auto;
}

.slide-block > .slide {
width: 3500px;
height: 400px;
position: absolute;
transition: 0.4s;
left: 0;
top: 0;
}

.slide-block > .slide > .item {
width: 700px;
height: 400px;
float: left;
}

.slide-arrow {
font-size: 50px;
}

.slide-arrow > .left ,
.slide-arrow > .right {
position: absolute;
padding: 160px 0;
color: rgba(255,255,255,0.5);
cursor: pointer;
}

.slide-arrow > .left:hover ,
.slide-arrow > .right:hover {
color: rgba(255,255,255,1);
transition: 0.4s;
}

.slide-arrow > .left {
left: 20px;
}

.slide-arrow > .right {
right: 20px;
}

.anchor {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
}

.anchor > div {
width: 15px;
height: 15px;
border-radius: 10px;
background-color: rgba(255,255,255,0.5);
display: inline-block;
margin: 0 4px;
}

.anchor > div:hover,
.anchor > .active{
background-color:rgba(255,255,255,1);
}




JS


$(window).on('load', function() {

var activeSlide = 1;
var activeNode = 1;

$(".left").on("click", function(){
if (activeSlide === 1){
activeSlide = 5;
}else {
activeSlide -= 1;
}
activeNode = activeSlide;
moveSlide(activeSlide);
lightAnchor(activeNode);
});
$(".right").on("click", function(){
if (activeSlide === 5){
activeSlide = 1;
}else {
activeSlide += 1;
}
activeNode = activeSlide;
moveSlide(activeSlide);
lightAnchor(activeNode);
});
$(".anchor div").on("click", function(){
activeSlide = $(this).attr("data-anchor");
moveSlide(activeSlide);
lightAnchor(activeSlide);
});

function moveSlide(targetSlide){
var targetNode = targetSlide - 1;
var distence = targetNode * 700;
$(".slide").css("left", - distence);
}

function lightAnchor(targetAncor){
$(".active").removeClass("active");
$("[data-anchor='"+targetAncor+"']").addClass("active");
}

// .item data-color속성 받아서 background로 넣기
$(".item").each(function(){
$(this).css("background-color", $(this).attr("data-color"));
});
})



'Coding' 카테고리의 다른 글

es6 ::: getter & setter  (0) 2018.06.19
ES6 ::: 배열  (0) 2018.06.18
Jquery ::: 반복연습 1번째  (0) 2018.06.12
ODOO 11 ::: ORM API - Environment  (0) 2018.04.27
rpc  (0) 2018.04.26

Jquery


반복연습 1번째


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>슬라이드 만들기 1번째</title>

<script src="https://use.fontawesome.com/3398c33652.js"></script>
<script src="jquery.js"></script>
</head>
<style>
* {
border: 0;
padding: 0;
margin: 0;
}
.slide_box {
width:700px;
height:400px;
position: relative;
overflow: hidden;
margin: 10% auto;
}
.slide {
width: 2100px;
height: 400px;
border: 1px solid #aaa;
position: absolute;
transition: 0.4s;
transition-timing-function: ease-in-out;
left: 0;
top: 0;
}
.slide-item {
width:700px;
height: 400px;
float: left;
}
.slide_nav {
text-align: center;
width: 100%;
position: absolute;
bottom: 20px;
}
.slide_nav > ul > li {
background: rgba(255,255,255,.5);
width: 15px;
height: 15px;
margin:0 4px;
border-radius: 10px;
display: inline-block;
cursor: pointer;
}
.slide_nav > ul > li:hover {
background: rgba(255,255,255,1);
}
.slide_nav ul .active {
background: rgba(255,255,255,1);
}
.arrow{
font-size: 50px;
cursor: pointer;
}
.arrow > .left:hover,
.arrow > .right:hover{
transition: 0.4s;
color: rgba(255,255,255,1);
}
.arrow > .left {
position: absolute;
top: 40%;
left: 20px;
color: rgba(255,255,255,.5);
}
.arrow > .right {
position: absolute;
top: 40%;
right: 20px;
color: rgba(255,255,255,.5);
}
</style>
<body>

<div class="slide_box">
<div class="slide">
<div class="slide-item" data-node="1" data-color="red"></div>
<div class="slide-item" data-node="2" data-color="blue"></div>
<div class="slide-item" data-node="3" data-color="black"></div>
</div>
<div class="slide_nav">
<ul>
<li class="active" data-anchor="1"></li>
<li data-anchor="2"></li>
<li data-anchor="3"></li>
</ul>
</div>
<div class="arrow">
<div class="left" data-direction="left"><i class="fa fa-angle-left" aria-hidden="true"></i></div>
<div class="right" data-direction="right"><i class="fa fa-angle-right" aria-hidden="true"></i></div>
</div>
</div>


<script>
$(window).on('load', function(){

// 현재 slide를 담기위한 activeSlide 변수
var activeSlide = 1;

// 현재 slide와 연결된 노드를 담기 위한 node 변수
var node = 1;


// .arrow > div를 클릭하면
$('.arrow div').on('click', function(){

// direction 변수에 나 자신의 data-direction 속성값을 담을거야.
var direction = $(this).attr('data-direction');

// direction이 'lift'와 일치하고
if (direction === 'left'){

// activeSlide가 1이면
if(activeSlide === 1){

// activeSilde를 5로 바꿀거야.
activeSlide = 3;

// activeSlide가 1이 아니면
}else {

//activeSlide에서 1을 뺄거야.
activeSlide = activeSlide - 1;
}


// direction이 'right'와 일치하고
}else if (direction === 'right'){

// activeSlide가 5면
if (activeSlide === 3){

// activeSlide를 1로 바꿀거야.
activeSlide = 1;

// activeSlide가 5가 아니면
}else {

// activeSlide에 1을 더할거야.
activeSlide = activeSlide + 1;
}

// 모든 조건이 false면 에러메세지를 띄울거야.
}else{
alert('error');
}

// node변수는 현재 activeSlide와 같은 값을 가지고있어야하므로
// node변수에 activeSlide값을 넣을거야.
node = activeSlide;

// moveSlide메소드로 현재 activeSlide를 움직일거야. *기능발사!*
moveSlide(activeSlide);

// lightNav메소드로 현재 activeSlide와 매치되는 slide_nav 색을 강조할거야. *기능발사!*
lightNav(activeSlide);
});

// .slide_nav 안에 li들을 클릭하면
$('.slide_nav li').on('click', function(){

// node 변수에 data-anchor속성을 받아서 클릭한 li안에 넣어줄거야.
node = $(this).attr('data-anchor');

// activeSlide에 node를 int로 형변환해서 넣어줄거야 (속성을 받아오면 문자열로 받아와서 형변환 해야돼)
activeSlide = parseInt(node);

// moveSlide메소드로 클릭한 node값에 매칭된 activeSlide를 움직일거야. *기능발사!*
moveSlide(activeSlide);

// lightNav메소드로 클릭한 node값에 매칭된 activeSlide를 움직일거야. *기능발사!*
lightNav(activeSlide);
});

// .slide-item에 하나씩 반복해서 메소드를 실행할거야
$('.slide-item').each(function (){

// 반복된 요소 하나하나마다 요소의 data-color속성을 읽어서 css로 넣어줄거야
$(this).css("background-color", $(this).attr('data-color'));
});

// 슬라이드를 움직이게하는 moveSlide메소드를 만들거야.
// targetSlide에는 activeSlide값이 들어갈거야
function moveSlide(targetSlide) {

// 시작 슬라이드는 구하는 targetNod는 0부터 시작해야하기때문에 -1 해줘야돼
var targetNod = targetSlide - 1;

// 한번 슬라이드 될 때 움직일 left만큼 targetNod에 곱해서 distence변수에 넣어줄거야
var distence = targetNod * 700;

// .slide의 css에 left를 distence만큼 빼줄거야
$('.slide').css('left', - distence);
};

// 슬라이드가 움직일때마다 현재 슬라이드와 매칭되는 slide_nav를 밝게 해줄거야
function lightNav(anchor){

//밝게해주는 스타일이 들어있는 .active 클래스를 지워줄거야
$('.active').removeClass('active');

//현재 anchor에 따라 active클래스를 추가해줄거야
$('[data-anchor="'+anchor+'"]').addClass('active');
}
});
</script>
</body>
</html>



'Coding' 카테고리의 다른 글

ES6 ::: 배열  (0) 2018.06.18
선택 안됨 Jquery ::: 반복연습 2번째  (0) 2018.06.12
ODOO 11 ::: ORM API - Environment  (0) 2018.04.27
rpc  (0) 2018.04.26
ODOO 11 ::: ORM API - 레코드세트  (0) 2018.04.26

ORM API


Environment


Environment는 ORM에서 사용하는 다양한 문맥 데이터를 저장합니다. 

데이터베이스 커서 (데이터베이스 쿼리의 경우) 및 현재 사용자(엑세스 권한 확인의 경우) 및 현재 컨텍스트(임의 메타 데이터 저장의 경우) 입니다. 

environment는 캐시 또한 저장합니다.


모든 레코드 세트는 환경변수를 가지며, 환경변수는 env로 사용하여 엑세스 할 수 있스며 현재 사용자(user), 커서(cr) 또는 컨텍스트(context)에 대한 엑세스 권한을 제공합니다.   


>>> records.env
<Environment object ...>
>>> records.env.user
res.user(3)
>>> records.env.cr
<Cursor object ...)


다른 레코드 세트에서 레코드 세트를 만들면 환경이 상속됩니다.

환경은 다른 모델에서 빈 레코드 세트를 가져와서 해당 모델을 쿼리하는데 사용할 수 있습니다.


>>> self.env['res.partner']
res.partner
>>> self.env['res.partner'].search([['is_company', '=', True], ['customer', '=', True]])
res.partner(7, 18, 12, 14, 17, 19, 8, 31, 26, 16, 13, 20, 30, 22, 29, 15, 23, 28, 74)




환경 설정


environment는 레코드 세트에서 사용자 정의 할 수 있습니다.

변경된 환경을 사용하여 새 버전의 레코드 집합을 반환합니다.


sudo()

제공된 사용자 세트를 사용하여 새 환경을 만들고 아무것도 제공되지 않으면 

관리자 권한으로(안전한 환경에서 엑세스 권한 / 규칙을 무시하기 위해) 새 environment를 사용하여 호출 된 레코드 세트의 복사본을 반환합니다.


# 관리자 권한으로 partner 객체 생성 env['res.partner'].sudo().create({'name': "A Partner"}) # "public" user가 볼수있는 partner를 나열합니다. public = env.ref('base.public_user') env['res.partner'].sudo(public).search([])



with_context()
  • 현재 환경의 컨텍스트를 대체하는 단일 위치 매개변수를 취할 수 있습니다.
  • 현재 환경의 컨텍스트 또는 1단계에서 설정한 컨텍스트에 추가되는 키워드에 따라 원하는 수의 매개변수를 취할 수 있습니다.

# 파트너를 찾아 보거나 파트너가 없는 경우 지정된 시간대를 사용하여 파트너를 만듭니다. # 찾음 env['res.partner'].with_context(tz=a_tz).find_or_create(email_address)



with_env()

기존 환경을 완전히 대체합니다.


'Coding' 카테고리의 다른 글

선택 안됨 Jquery ::: 반복연습 2번째  (0) 2018.06.12
Jquery ::: 반복연습 1번째  (0) 2018.06.12
rpc  (0) 2018.04.26
ODOO 11 ::: ORM API - 레코드세트  (0) 2018.04.26
HTTP ::: 프로토콜 구조  (0) 2018.04.26

rpc사용법



var Rpc = require('web.rpc');    //rpc를 쓴다라는뜻 꼭 정의하고 시작해야함






Rpc.query({              

                         model: 'ir.model.data',               // 테이블명

                         method: 'get_object_reference',         // py의 정의된 함수 호출 (name에 넣을건지 date에 넣을건지 컬럼정의는 여기서한다.)

                         args: ['boram', 'view_boram_purchasepart_tree'],     //값이 들어감(넣을 값을 넣으면됨.)

                   })

                   .then(function(result){

                 

                       var view_id = result[1];

}




데이터 넣을때 


rpc.query({
model: 'website.board', // 테이블명
method: 'search_read',  // py의 정의된 함수 호출 (뭘 하려고하는지 정의한다.)
args: [[id], ['partname','maker']] //입력값의 매개변수가 들어감.

})
.then(function(result)
{

리턴 값 (성공or실패or반환값)

}





데이터 받아올때 


rpc.query({
model: 'website.board', // 테이블명
method: 'search_read',  // py의 정의된 함수 호출 (뭘 하려고하는지 정의한다.)
domain: [], // 필터같은 개념
fields: ['name', 'date_release'], // 받아올 데이터 컬럼명
sortBy: ['date_release desc'], // 데이터 정렬
})
.then(function(data)
{

//받아온 데이터는 여기서 사용한다.

}





odoo 모델 데이터 작성방법


<Model>.create(values)                 < 모델에 새로운 레코드를 생성합니다. return:생성된 레코드
<Recordset>.write(values)                 < 레코드 세트의 필드값을 업데이트합니다. return : 아무것도 반환하지않음

<Recordset>.unlink()                 < 데이터베이스에서 레코드를 삭제함. return : 아무것도 반환하지않음


'Coding' 카테고리의 다른 글

Jquery ::: 반복연습 1번째  (0) 2018.06.12
ODOO 11 ::: ORM API - Environment  (0) 2018.04.27
ODOO 11 ::: ORM API - 레코드세트  (0) 2018.04.26
HTTP ::: 프로토콜 구조  (0) 2018.04.26
Odoo 11 ::: Snippets Pagination  (0) 2018.04.17

ORM API


레코드 세트



모델에 정의 된 메서드는 레코드 세트에서 실행되며, 그 레코드세트는 self 입니다.


class AModel(models.Model): _name = 'a.model' def a_method(self): # self는 처음부터 끝까지 모든 레코드 사이에 있을 수 있습니다. # database self.do_operation()


레코드 세트를 반복하면 단일 레코드의 새로운 세트("싱글톤")를 얻을 수 있습니다.

파이썬 문자열을 반복하는 것과 같이 단일 문자의 문자열을 생성합니다.


def do_operation(self):
    print self # => a.model(1, 2, 3, 4, 5)
    for record in self:
        print record # => a.model(1), then a.model(2), then a.model(3), ...




필드 엑세스


레코드 세트는 "Active Record" 인터페이스를 제공합니다.

모델 필드는 레코드에서 직접 읽고 쓸 수 있지만 싱글톤(단일 레코드 레코드세트)에서만 가능합니다.

필드의 값을 걸정하면 데이터베이스를 업데이트합니다.


>>> record.name
Example Name
>>> record.company_id.name
Company Name
>>> record.name = "Bob"


여러 레코드에서 필드를 읽거나 쓰려고 하면 오류가 발생합니다.


관계형 필드(Many2one, One2many, Many2many)에 엑세스 하면 필드가 설정되지 않은 경우 비어있는 레코드 세트가 항상 반환됩니다.



주의

필드에 대한 각 할당은 데이터베이스 업데이트를 트리거합니다.
여러 필드를 동시에 설정하거나 여러 레코드의 필드를 동일한 값으로 설정할 때 write()를 사용합니다.

# 3 * len(records) database updates
for record in records:
    record.a = 1
    record.b = 2
    record.c = 3

# len(records) database updates
for record in records:
    record.write({'a': 1, 'b': 2, 'c': 3})

# 1 database update
records.write({'a': 1, 'b': 2, 'c': 3})



레코드 캐시와 프리페칭

Odoo는 레코드 필드에 대한 캐시를 유지 관리하므로 모든 필드 엑세스가 데이터베이스 요청을 발행하는 것은 아닙니다.
이는 성능 저하로 이어질 수 있습니다.
다음 예제에서는 첫번째 명령문에 대해서만 데이터베이스를 쿼리합니다.

record.name             # 첫번째 엑세스는 데이터베이스에서 값을 읽습니다.
record.name             # 두번째 엑세스는 캐시에서 값을 가져옵니다.

한번에 하나의 레코드에서 하나의 필드를 읽지 않으려면 Odoo는 좋은 결과를 얻기 위해 몇 가지 발견 방법에 따라 레코드와 필드를 프리페치합니다.
필드가 주어진 레코드에서 읽혀지면 ORM은 실제로 더 큰 레코드 세트에서 해당 필드를 읽고 나중에 사용하기 위해 반환 된 값을 캐시에 저장합니다.
프리페치된 레코드 세트는 대게 레코드가 반복되는 레코드 세트 입니다.
게다가 모든 간단한 저장 필드 (boolean, integer, float, char, text, date, datetime, selection, many2one)는 모두 가져옵니다.
모델 테이블의 열에 해당하며 동일한 쿼리에서 효율적으로 가져옵니다.

partner가 1000레코드의 레코드세트인 다음 예제를 생각해보십시오.
프리페치가 없으면 루프는 데이터베이스에 대해 2000개의 쿼리를 작성합니다.
프리페칭을 사용하면 하나의 쿼리만 작성됩니다.

for partner in partners:
    print partner.name          # 첫번째 패스 프리페칭 'name' 과 'lang'
                                # (또 다른 필드) 모든 'partners'
    print partner.lang


프리페칭은 2차 레코드에서도 작동합니다. 
관계형 필드를 읽을 때, 그 값(레코드)은 향후 프리페칭 됩니다.
이 2차 레코드 중 하나에 엑세스 하면 동일한 모델의 모든 2차 레코드를 프리페치 합니다.

다음 예제는 partner와 country에 대한 두 개의 쿼리만 생성합니다.

countries = set() for partner in partners: country = partner.country_id # 첫번째 패스는 모든 partners를 프리페치합니다. countries.add(country.name) # 첫번째 패스는 모든 countries를 프리페치합니다.




Set 연산

레코드 세트는 변경 가능하지 않지만 동일한 모델의 세트를 다양한 세트 조작을 사용해 결합하여 새 레코드 세트를 반환 할 수 있습니다.
Set operations는 순서를 보존하지 않습니다.
  • record in set는 record(1-element의 레코드 세트 여야 함)가 set에 있는지 여부를 반환합니다. record not in set는 역 연산입니다.
  • set1 <= set2 와 set1 < set2 에서 set1이 subset인지 set2가 subset인지를 반환합니다. (resp. strict)
  • set1 >= set2set1 > set2 에서 set1이 superset인지 set2가 superset인지를 반환합니다. (resp. strict)
  • set1 | set2는 두 레코드 세트의 합집합을 반환하며, 두 레코드 세트에 합집합인 레코드를 포함하는 새 레코드 세트를 반환합니다.
  • set1 & set2는 두 레코드 세트의 교집합을 반환하며, 두 레코드 세트에 교집합인 레코드만 포함하는 새 레코드 세트를 반환합니다.
  • set1 - set2는 set2에 없는 set1 레코드만 포함하는 새 레코드 세트를 반환합니다.




기타 레코드 세트 연산


레코드 세트는 반복 가능하므로 일반적으로 파이썬 도구를 변환(map(), sorted(), ifilter(), ...)할 때 사용할 수 있지만 
list나 반복자를 반환하거나, 결과에서 메서드를 호출하는 기능을 제거하거나, 설정작업을 사용합니다.

따라서 레코드 세트는 가능한 경우 레코드 세트를 반환하는 다음 작업을 제공합니다.

filtered()
  • 제공된 조건자 함수를 만족하는 레코드만 포함하는 레코드세트를 반환합니다. 속성은 true 또는 false인 필드로 필터링 할 문자열 일 수도 있습니다.

# company가 현재 사용자인 레코드만 보관 records.filtered(lambda r: r.company_id == user.company_id) # partner가 company인 레코드만 보관 records.filtered("partner_id.is_company")



sorted()
  • 제공된 키 함수로 정렬 된 레코드 세트를 반환합니다. 키가 제공되지 않으면 모델의 기본 정렬 순서를 사용하십시오.
# name으로 레코드 정렬
records.sorted(key=lambda r: r.name)


mapped()
  • 제공된 함수를 레코드 세트의 각 레코드에 적용하고 결과가 레코드 세트인 경우 레코드 세트를 반환합니다.
# 세트의 각 레코드에 대해 두 개의 필드를 합산하는 list를 반환합니다.
records.mapped(lambda r: r.field1 + r.field2)

제공된 함수는 필드 값을 가져오는 문자열 일 수 있습니다.

# name 리스트를 반환합니다. records.mapped('name') # partner 레코드 세트를 반환합니다. record.mapped('partner_id') # 모든 partner bank의 합집합을 반환하며 중복 된 값은 제거됩니다. record.mapped('partner_id.bank_ids')



'Coding' 카테고리의 다른 글

ODOO 11 ::: ORM API - Environment  (0) 2018.04.27
rpc  (0) 2018.04.26
HTTP ::: 프로토콜 구조  (0) 2018.04.26
Odoo 11 ::: Snippets Pagination  (0) 2018.04.17
Odoo 11 ::: Fields Type에 대해 알아보자 (3)  (0) 2018.04.10

 HTTP 프로토콜 구조


https, request, response, 주요 상태코드



1. 특징

  • 인터넷상에서 데이터를 주고받기 위한 서버/클라이언트 모델을 따르는 전송 프로토콜

  • 애플리케이션 레벨의 프로토콜로 TCP/IP 위에서 작동
  • 클라이언트에서 요청(request)을 보내면 서버는 요청을 처리해서 응답(response)
  • 80번  port이용


비상태연결 (Stateless, Connectless)


서버에 연결하고 요청해서 응답을 받으면 연결을 끊어버린다.


  • 장점 : 접속유지 최소화, 불특정 다수를 대상으로 하는 서비스에 유리
  • 단점 : 연결을 끊어버리기 때문에 클라이언트의 이전 상태를 알 수 없음, 따라서 로그인을 해도 정보유지 불가. 이를 해결하기 위해 쿠키등을 이용


Keep Alive


HTTP 1.1부터는 keep-alive 기능을 지원

HTTP는 하나의 연결에 하나의 요청을 하는 것을 기준으로 설계가 되어, 문서에 20여개의 파일이 있다면 계속 연결하고 다운하고 연결을 끊어야 한다.

TCP통신 과정에서 비용이 많이 소모함. 따라서 Keep Alive 기능 등장.

지정된 시간동안 연결을 끊지 않고 요청을 계속해서 보낼 수 있다.



HTTPS


SSL은 전자상거래에서의 데이터 보안을 위해서 개발한 통신 레이더다.

SSL은 표현계층의 프로토콜로 응용 계층 아래에 있기 때문에 어떤 응용계층의 데이터라도 암호화해서 보낼 수 있다.




  • HTTPS의 기분 포트번호는 443

  • HTTP에 비해 많이 느림



2. Request


메세지 구조


요청라인 : GET / HTTP / 1.1

  • 요청 메소트 : GET, POST, PUT, DELETE
  • 요청 URL
  • HTTP 버전

요청헤더 : 키 - 값 방식으로 들어감

  • Accept : 클라이언트가 받을 수 있는 컨텐츠
  • Cookie : 쿠키
  • Content-Type : 메세지 바디 종류
  • Content-Length : 메세지 바디 길이
  • if-Modified-Since : 특정 날짜 이후에 변경됐을때만

요청 바디 (엔티티)



Content-Type과 Body


참조문서 : https://www.w3.org/Protocols/rfc1341/4_Content-Type.html


1. form 형태 : URLEncoded 방식

  • application / x-www-form-urlencoded
  • 메세지 바디 : 쿼리 문자열

2. json 형태

  • application / json

3. 멀티파트 형태 : 이진파일 넘길 때 사용, 하나의 메세지 바디에 파트를 나눠서 작성

  • boundary는 파트 구분자
  • multipart / form-data : boundary = frontier



3. Response


메세지 구조


응답 라인

  • 버전
  • 상태코드
  • 상태 메세지 : HTTP/1.1 200 OK

응답 헤더

  • Content-Type : 바디 데이터의 타입
  • Content-Length : 바디 데이터 크기
  • Set-Cookie : 쿠키 설정
  • ETag : 엔티티 태그

응답 바디 : HTML, JSON, Octet Stream 등이 있다.



상태 코드


1xx : 정보


2xx : 성공

  • 200 : OK. 요청 성공
  • 201 : Created. 생성 요청 성공
  • 202 : Accepted. 요청 수락 (처리 보장 X)
  • 204 : 성공했으나 돌려줄게 없음

3xx : 리다이렉션

  • 300 : Multiple choices. 여러 리소스에 대한 요청 결과 목록
  • 301, 302, 303 : Redirect. 리소스 위치가 변경된 상태
  • 304 : Not Modified. 리소스가 수정되지 않았음.

4xx : 클라이언트 오류

  • 400 : Bad Request. 요청 오류
  • 401 : Unauthorized. 권한 없음
  • 403 : Forbidden. 요청 거부
  • 404 : Not Found. 리소스가 없는 상태

5xx : 서버 오류

  • 500 : Internal Server Error. 서버가 요청을 처리 못함
  • 501 : Not Implemented. 서버가 지원하지 않는 요청
  • 503 : Service Unavailable. 과부화 등으로 당장 서비스가 불가능한 상태


Content-Type과 Body


주요 컨텐츠 타입은 아래와 같다.

  • text / plain, text / html
  • application / xml, application / json
  • image / png, image / jpg
  • audio / mp3, video / mp4



'Coding' 카테고리의 다른 글

rpc  (0) 2018.04.26
ODOO 11 ::: ORM API - 레코드세트  (0) 2018.04.26
Odoo 11 ::: Snippets Pagination  (0) 2018.04.17
Odoo 11 ::: Fields Type에 대해 알아보자 (3)  (0) 2018.04.10
Odoo 11 ::: Fields Type에 대해 알아보자 (2)  (1) 2018.04.09

Odoo 11 Snippets Pagination



templates.xml


<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="assets_frontend" inherit_id="website.assets_frontend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/linkup_theme/static/src/less/board.less" />

<script src="/linkup_theme/static/src/js/r3_snippets.js" type="text/javascript"/>
<script src="/linkup_theme/static/src/js/jquery.twbsPagination.js" type="text/javascript"></script>
</xpath>
</template>
</odoo>



snippets.xml


<!--게시판 -->
<template id="r3_2" name="board table">
<section class="section-md oe_snippet_body board_snippet">
<section class="container">
<h2>Board</h2>
<table class="table" id="page-content">
<tr>
<th>Name</th>
<th>Release date</th>
</tr>
</table>
<nav aria-label="Page navigation example" style="text-align: center;">
<ul class="pagination-sm" id="pagination"></ul>
</nav>
</section>

</section>
</template>



r3_snippets.js



odoo.define('r3_snippets', function(require)
{
"use strict";
var rpc = require('web.rpc'), //< 함수를가져옴
Animation = require('website.content.snippets.animation');


Animation.registry.board_snippet = Animation.Class.extend({
selector: '.board_snippet',
start: function()
{
var self = this;
_.each(this.$el.attr('class').split(/\s+/), function(cls)
{
if(cls.indexOf('board_snippet-show') == 0)
{
var number = parseInt(cls.substring('board_snippet-show'.length));
}
});
this.$el.find('td').parents('tr').remove();
rpc.query({
model: 'website.board',
method: 'search_read',
domain: [],
fields: ['name', 'date_release'],
sortBy: ['date_release desc'],
})
.then(function(data)
{
var totalCount = data.length; //db에 데이터 수
var countList = 9; // 한 페이지에 출력될 게시물 수
var totalPage = Math.floor(totalCount/countList); //전체 페이지 번호수
var page = 1; //현재 페이지 번호
var countPage = 5; //한 화면에 출력될 페이지 수
var startPage = Math.floor((page - 1) / 10) * 10 + 1; //시작 페이지
var endPage = startPage + countPage - 1; //마지막 페이지

if (endPage > totalPage) { // 마지막페이지가 전체페이지보다 크면
endPage = totalPage; // 마지막페이지를 전체페이지로 바꾼다.
}

if (totalCount > countList * totalPage){ // db에 데이터수가 1페이지 게시물수 * 전체 페이지 수 보다 많으면
totalPage+=1; // 전체 페이지에 1을 더한다.
}

if (totalPage < page){ // 현재 페이지가 전체 페이지수보다 크면
page = totalPage; // 현재 페이지를 전체 페이지로 바꾼다.
}

var paging = function(page) { //paging 함수를 정의한다.
$("table").empty(); // table태그 안에 내용을 비운다.
var $table = self.$el.find('table'); // $table변수에 table태그를 담는다.
var startRow = (page - 1) * countList; // 시작줄
var endRow = page * countList; // 마지막줄
if (endRow >= totalCount) // 마지막줄이 db 데이터 수 보다 많거나 같으면
{
endRow = totalCount; // 마지막줄을 db데이터수로 바꾼다.
}

for (var i = startRow; i < endRow; i++){ // 시작줄부터 마지막줄의 크기만큼 아래내용을 반복한다.
$table.append( // $table변수 뒤에 아래 태그를 추가한다.
jQuery('<tr />') // tr태그를 추가한다.
.append(
jQuery('<td />').text(data[i].name), // website.board[i].name을 추가한다.
jQuery('<td />').text(data[i].date_release) // website.board[i].date_release를 추가한다.
)
);
}
}


$('#pagination').twbsPagination({
startPage: startPage, //시작 페이지
totalPages: totalPage, //총 페이지 갯수
visiblePages: countPage, //보여줄 페이지
onPageClick: function (event, page) { // 클릭하면
$('#page-content').text('Page ' + page);
paging(page); // paging 함수가 실행된다.
}
});
});

},
});
});



Odoo 11 필드 타입 3


속성 필드


속성 선언하기


속성은 특별한 필드입니다 : fields.property.


class res_partner(osv.osv):
    _name = "res.partner"
    _inherit = "res.partner"
    _columns = {
                'property_product_pricelist':
                                            fields.property(
                                'product.pricelist',
                        type='many2one',
                        relation='product.pricelist',
                        string="Sale Pricelist",
                                method=True,
                                view_load=True,
                                group_name="Pricelists Properties"),
    }


다음은 이 속성에 대한 .XML 파일에 기본값을 만들어야합니다.


<record model="ir.property" id="property_product_pricelist">
    <field name="name">property_product_pricelist</field>
    <field name="fields_id" search="[('model','=','res.partner'),
      ('name','=','property_product_pricelist')]"/>
    <field name="value" eval="'product.pricelist,'+str(list0)"/>
</record>


TIP


기본값이 다른 모듈의 자원을 가리키면 다음과 같이 ref 함수를 사용할 수 있습니다 : <field name="value" eval="'product.pricelist,'+str(ref('module.data_id'))"/>


form에 속성 배치하기


폼에 속성을 추가하려면 폼에 <properties /> 태그를 넣으면됩니다. 그러면이 개체와 관련된 모든 속성 필드가 자동으로 추가됩니다. 

사용자 시스템의 권한에 따라 시스템이 추가됩니다. (일부 사용자는 특정 속성을 변경할 수 있고 다른 사용자는 그렇지 않을 수 있습니다).


특성은 group_name 속성에 따라 섹션별로 표시됩니다. (이것은 분리 자 태그처럼 클라이언트에서 렌더링됩니다).



이게 어떻게 작동합니까?


fields.property 클래스는 fields.function을 상속하며 읽기 및 쓰기 메서드를 재정의합니다. 

이 필드의 유형은 many2one이므로 양식에서 many2one 함수와 같은 속성이 표시됩니다.


그러나 속성의 값은 ir.property 클래스 / 테이블에 완전한 레코드로 저장됩니다. 

저장된 값은 각 속성이 다른 객체를 가리킬 수 있기 때문에 many2one이 아닌 형식 참조 필드입니다. 

관리 메뉴에서 등록 정보 값을 편집하는 경우 이는 유형 참조 필드로 표시됩니다.


속성을 읽을 때이 프로그램은 읽고있는 객체의 인스턴스에 연결된 속성을 제공합니다. 

이 객체에 값이 없으면 시스템에서 기본 속성을 제공합니다.


프로퍼티의 정의는 다른 필드와 마찬가지로 ir.model.fields 클래스에 저장됩니다. 

속성의 정의에서 속성으로 변경할 수있는 그룹을 추가 할 수 있습니다.



속성 또는 일반 필드 사용


새 기능을 추가하려면 속성을 일반 필드로 구현하도록 선택해야합니다. 개체를 상속하고이 개체를 확장하려면 일반 필드를 사용하십시오. 

새 속성이 객체와 관련이 없지만 외부 개념에 관련된 경우 속성을 사용합니다.


다음은 일반 필드 또는 속성 중에서 선택할 때 도움이되는 몇 가지 팁입니다.


일반 필드는 객체를 확장하여 더 많은 피쳐 또는 데이터를 추가합니다.


속성은 객체에 첨부되고 특별한 기능을 가진 개념입니다.


예 )

- 회사에 따라 동일한 부동산에 대한 다른 가치 - 필드 당 권한 관리 - 그것은 자원들 간의 연결고리입니다 (many2one)


예제1: Account Receivable


특정 파트너에 대한 기본 "Account Receivable"은 다음과 같은 이유로 인해 이 속성으로 구현됩니다.


- 이 개념은 파트너가 아닌 계정 차트와 관련된 개념이므로 파트너 폼에 표시되는 계정 속성입니다. 회계사의 경우이 필드에서 권한을 관리해야하며 파트너 객체에 적용되는 것과 동일한 권한이 아닙니다. 따라서 파트너 양식의 이 필드에만 특정 권한이 있습니다. 회계사만 파트너의 채권을 변경할 수 있습니다. - 이것은 여러 회사 필드입니다. 동일한 파트너는 사용자가 속한 회사에 따라 다른 채권값을 가질 수 있습니다. 다중 회사 시스템에는 회사 당 하나의 계정 차트가 있습니다. 파트너의 계정 채권은 판매 주문을 한 회사에 따라 다릅니다. - 기본 계정 채권은 모든 파트너에 대해 동일하며 일반 속성 메뉴 (관리)에서 구성됩니다.


TIP


한 가지 재미있는 점은 속성이 "스파게티"코드를 피하는 것입니다. 

계정 모듈은 파트너 (base) 모듈에 따라 다릅니다. 하지만 회계 모듈없이 파트너 (base) 모듈을 설치할 수 있습니다. 

파트너 개체의 계정을 가리키는 필드를 추가하면 두 개체가 서로 종속됩니다. 

유지 보수 및 코드 작성이 훨씬 어렵습니다 (예 : 두 테이블이 서로 가리키는 경우 테이블 제거를 시도).



- 예제 2: Product Times



제품 만료 모듈은 제품과 관련된 모든 지연을 제거 날짜, 제품 시간등등을 구현합니다.이 모듈은 식품 산업에 매우 유용합니다.


이 모듈은 product.product 객체를 상속 받아 새 필드를 추가합니다.


class product_product(osv.osv):

    _inherit = 'product.product'
    _name = 'product.product'
    _columns = {

        'life_time': fields.integer('Product lifetime'),
        'use_time': fields.integer('Product usetime'),
        'removal_time': fields.integer('Product removal time'),
        'alert_time': fields.integer('Product alert time'),
        }

product_product()


이 모듈은 product.product 객체에 간단한 필드를 추가합니다. 속성을 사용하지 않았습니다. 

이유는 다음과 같습니다.


우리는 제품을 확장하고 life_time 필드는 제품과 관련된 개념이며 다른 객체에는 관련되지 않습니다. 우리는 필드 당 올바른 관리가 필요하지 않으며, 다른 지연은 모든 제품을 관리하는 동일한 사람들이 관리합니다.




+ Recent posts