쿠버네티스,쿠버플로우
던전앤파이터 시세 예측[6]
세용용용용
2023. 9. 12. 11:23
장고에서 던파 아바타 정보를 input으로 받아 모델predict를 하여 예측값을 출력해보자!!
input으로 받을 컬러 목록을 테이블에 저장해보자
테이블 생성
CREATE TABLE input_list (
title TEXT,
jobname TEXT,
emblem TEXT
);
테이블에 input_list값 넣는 코드
title_data = df['title'].drop_duplicates()
jobname_data = df['jobname'].drop_duplicates()
emblem_data = df['emblem'].drop_duplicates()
import pymysql
# 연결 정보 설정
host = "10.103.132.127"
port = 3306
database = "donpa_item"
user = "root"
password = "1234"
# 연결
connection = pymysql.connect(
host=host,
port=port,
user=user,
password=password,
database=database
)
try:
# 커서 생성
cursor = connection.cursor()
# 데이터 입력 (존재하지 않는 데이터만 입력)
for item in title_data:
sql = f"INSERT INTO input_list (title) SELECT '{item}' FROM DUAL WHERE NOT EXISTS (SELECT * FROM input_list WHERE title = '{item}')"
cursor.execute(sql)
for item in jobname_data:
sql = f"INSERT INTO input_list (jobname) SELECT '{item}' FROM DUAL WHERE NOT EXISTS (SELECT * FROM input_list WHERE jobname = '{item}')"
cursor.execute(sql)
for item in emblem_data:
sql = f"INSERT INTO input_list (emblem) SELECT '{item}' FROM DUAL WHERE NOT EXISTS (SELECT * FROM input_list WHERE emblem = '{item}')"
cursor.execute(sql)
# 커밋
connection.commit()
print(f"{len(title_data)}개의 레코드를 입력했습니다.")
print(f"{len(jobname_data)}개의 레코드를 입력했습니다.")
print(f"{len(emblem_data)}개의 레코드를 입력했습니다.")
except Exception as e:
# 에러 발생 시 롤백
connection.rollback()
print(f"데이터 입력 중 오류 발생: {str(e)}")
finally:
# 연결 종료
connection.close()
장고 models.py 해당 테이블을 추가해준다
class InputList(models.Model):
title = models.TextField(blank=True, null=False, primary_key=True)
jobname = models.TextField(blank=True, null=True)
emblem = models.TextField(blank=True, null=True)
class Meta:
managed = False
db_table = 'input_list'
views.py도 수정해주자
aabata.html 에서 해당 테이블을 사용할것이기에
from .models import InputList
def aabata_view(request):
# aabata.html 템플릿 렌더링
items = InputList.objects.all()
price = Goldprice.objects.latest('date')
return render(request, 'aabata.html', {'items': items, 'price': price})
최종 aabata.html
<!DOCTYPE html>
<html>
<head>
<title>Item List</title>
<style>
/* 제목 */
h1 {
font-size: 46px; /* 큰 제목 크기로 변경 */
color: #f7e706; /* 게임 색상으로 변경 */
text-align: center;/* 제목 가운데 정렬*/
}
/* 메뉴 스타일링 */
ul.menu {
list-style-type: none;
margin: 0;
padding: 0;
text-align: center;
padding: 10px 0; /* 메뉴 항목 위아래로 간격 추가 */
}
ul.menu li {
display: inline;
margin-right: 20px;
font-size: 40px;
}
ul.menu li a {
color: rgb(255, 255, 255);
text-decoration: none;
padding: 10px 20px; /* 각 메뉴 항목의 내부 여백 추가 */
border-radius: 5px; /* 각 메뉴 항목을 둥글게 꾸미기 */
/* background-color: #534747; /* 배경색 추가 */
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); /* 그림자 효과 추가 */
transition: background-color 0.3s, transform 0.2s; /* 호버 효과를 위한 트랜지션 설정 */
}
ul.menu li a:hover {
background-color: #4e2626; /* 호버 시 배경색 변경 */
transform: translateY(-2px); /* 호버 시 약간 위로 이동 효과 */
}
/* 배경 이미지 추가 */
body {
background-image: url('https://bbscdn.df.nexon.com/data7/commu/201712/205032_5a44da887e6a8.jpg');
background-size: cover;
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
position: relative;
z-index: 0;
}
/* select 스타일링 */
select, input {
padding: 10px;
font-size: 16px;
margin: 5px 0;
}
label {
display: inline-block;
width: 80px; /* 라벨 너비 조절 */
}
/* 결과 표시 스타일링 */
#resultDiv {
font-size: 20px;
text-align: center;
margin-top: 20px;
}
/* 확인 버튼 스타일링 */
#confirmButton {
display: block;
margin: 20px auto; /* 가운데 정렬 */
padding: 10px 20px;
font-size: 24px; /* 버튼 크기 키우기 */
background-color: #4e2626; /* 배경색 변경 */
color: #fff; /* 텍스트 색상 변경 */
border: none;
border-radius: 5px;
cursor: pointer;
}
/* 추가된 텍스트 스타일링 */
.input-label {
display: block;
font-size: 20px;
text-align: center;
margin-top: 10px;
}
/* select 요소 스타일링 */
.select-container {
text-align: center;
}
.select-container select {
padding: 10px;
font-size: 16px;
margin: 5px;
}
/* 금일 예상 가격 스타일링 */
#resultDiv {
font-size: 30px; /* 글꼴 크기 키우기 */
text-align: center;
margin-top: 20px;
color: #12e612; /* 색상 변경 */
opacity: 0; /* 초기에는 투명하게 설정 */
transform: translateY(20px); /* 초기 위치를 아래로 설정 */
transition: opacity 0.5s, transform 0.5s; /* 나타날 때 효과를 위한 트랜지션 설정 */
}
/* 추가된 텍스트 스타일링 */
.input-label {
display: block;
font-size: 20px;
text-align: center;
margin-top: 10px;
color: #12e612; /* 글씨색을 원하는 색상으로 변경 */
}
</style>
</head>
<body>
<ul class="menu">
<li><a href="/">아이템 시세</a></li>
<li><a href="/aabata/">아바타 시세</a></li>
<li><a href="/event/">진행 중 이벤트</a></li>
<li><a href="/news/">던파 소식</a></li>
</ul>
<h1>던전앤파이터 아바타</h1>
<!-- select 요소 추가 -->
<div class="input-label">Title:
<select id="select1">
{% for item in items %}
{% if item.title %}
<option value="{{ item.title }}">{{ item.title }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="input-label">Jobname:
<select id="select2">
{% for item in items %}
{% if item.jobname %}
<option value="{{ item.jobname }}">{{ item.jobname }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="input-label">Emblem:
<select id="select3">
{% for item in items %}
{% if item.emblem %}
<option value="{{ item.emblem }}">{{ item.emblem }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<!-- 두 번째 행: Day of the week, Year, Month, Day -->
<div class="input-label">Day of the week:
<select id="select4">
<!-- JavaScript를 사용하여 요일 옵션 추가 -->
</select>
<script>
// 요일 배열 생성
var daysOfWeek = ["Sunday", "Saturday", "Friday", "Monday", "Thursday", "Tuesday", "Wednesday"];
// select 요소 가져오기
var selectElement = document.getElementById("select4");
// 요일 배열을 반복하면서 옵션 요소 추가
for (var i = 0; i < daysOfWeek.length; i++) {
var option = document.createElement("option");
option.value = daysOfWeek[i];
option.text = daysOfWeek[i];
selectElement.appendChild(option);
}
</script>
</div>
<!-- year, month, day 입력 필드 추가 -->
<div class="input-label">Year:
<input type="number" id="year" name="year" min="2000" max="2099" step="1" placeholder="Enter year">
</div>
<div class="input-label">Month:
<input type="number" id="month" name="month" min="1" max="12" step="1" placeholder="Enter month">
</div>
<div class="input-label">Day:
<input type="number" id="day" name="day" min="1" max="31" step="1" placeholder="Enter day">
</div>
<!-- 확인 버튼 추가 -->
<button id="confirmButton">확인</button>
<!-- 결과를 표시할 div 추가 -->
<div id="resultDiv"></div>
<script>
var resultDiv = document.getElementById("resultDiv");
document.getElementById("confirmButton").addEventListener("click", function () {
var selectedTitle = document.getElementById("select1").value;
var selectedJobname = document.getElementById("select2").value;
var selectedEmblem = document.getElementById("select3").value;
var sell = parseFloat("{{ price.sell }}");
var buy = parseFloat("{{ price.buy }}");
var year = parseInt(document.getElementById("year").value);
var month = parseInt(document.getElementById("month").value);
var day = parseInt(document.getElementById("day").value);
var day_name = document.getElementById("select4").value;
// JavaScript 객체로 데이터 준비
var data = {
'selectedTitle': selectedTitle,
'selectedJobname': selectedJobname,
'selectedEmblem': selectedEmblem,
'sell': sell,
'buy': buy,
'year': year,
'month': month,
'day': day,
'day_name': day_name,
};
// AJAX를 사용하여 데이터를 서버로 전송
var xhr = new XMLHttpRequest();
xhr.open('POST', '/process_data/', true); // URL을 수정해야 합니다.
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
xhr.send(JSON.stringify(data));
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 서버에서의 응답 처리
var response = JSON.parse(xhr.responseText);
// 결과를 표시할 위치에 표시
resultDiv.innerHTML = "금일 예상 가격:" + response.message;
resultDiv.style.opacity = 1;
resultDiv.style.transform = "translateY(0)";
} else {
// 오류 처리
resultDiv.innerHTML = 'Error: ' + xhr.status;
}
}
};
});
</script>
</body>
</html>
select, input으로 입력받은 값을 처리할
views.py
import pandas as pd
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
@csrf_exempt
def process_data(request):
if request.method == 'POST':
try:
# POST 요청에서 데이터 추출
data = json.loads(request.body.decode('utf-8'))
selectedTitle = data['selectedTitle']
selectedJobname = data['selectedJobname']
selectedEmblem = data['selectedEmblem']
sell = data['sell']
buy = data['buy']
year = data['year']
month = data['month']
day = data['day']
day_name = data['day_name']
# 데이터 프레임 생성
df = pd.DataFrame({
'title': [selectedTitle],
'jobname': [selectedJobname],
'emblem': [selectedEmblem],
'sell': [float(sell)],
'buy': [float(buy)],
'year': [int(year)],
'month': [int(month)],
'day': [int(day)],
'day_name': [day_name]
})
# 여기에서 데이터프레임을 원하는 방식으로 처리
df['sell'] = df['sell'].astype(float)
df['buy'] = df['buy'].astype(float)
df['year'] = df['year'].astype(int)
df['month'] = df['month'].astype(int)
df['day'] = df['day'].astype(int)
# 데이터프레임 스케일링
obj_col = df.select_dtypes(include='object').columns
from sklearn.preprocessing import StandardScaler
# 스케일러 불러오기
import joblib
sds = joblib.load('/home/user/donpa/pybo/scaler.pkl')
df_sc = sds.transform(df.drop(columns = obj_col))
df_sc = pd.DataFrame(df_sc, columns = df.drop(columns = obj_col).columns)
# object 타입 컬럼 붙여주기
for i in obj_col:
df_sc[i] = df[i]
# 원핫 인코딩 돌려주자
from sklearn.preprocessing import OneHotEncoder
encoder = joblib.load('/home/user/donpa/pybo/encoder.pkl')
# 범주형 열만 선택
obj_df = df_sc.select_dtypes(include='object')
# 숫자형 열만 선택
no_obj_df = df_sc.select_dtypes(exclude='object')
# 범주형 열을 원핫 인코딩
encoded_features = encoder.transform(obj_df)
# 인코딩된 결과를 데이터프레임으로 변환
encoded_df = pd.DataFrame(encoded_features.toarray(), columns=encoder.get_feature_names(obj_df.columns))
# 인코딩된 범주형 열과 숫자형 열을 합침
df_sc_encoding = pd.concat([no_obj_df[:len(df_sc)] , encoded_df[:len(df_sc)]], axis = 1)
# 컬럼 특수문자 제거
import re
# 데이터프레임의 컬럼 이름에서 특수 문자를 제거하고 변경할 새로운 컬럼 이름 리스트 생성
new_columns = []
for old_column in df_sc_encoding.columns:
new_column = re.sub(r'[^\w\s]', '', old_column) # 특수 문자 제거
new_columns.append(new_column)
# 컬럼 이름을 새로운 이름으로 설정
df_sc_encoding.columns = new_columns
# 모델을 가져와 predict하자
import xgboost as xgb
xgb = joblib.load('/home/user/donpa/pybo/xg_model.pkl')
pred_result = xgb.predict(df_sc_encoding)[0]
pred_result = float(pred_result)
# 결과를 JSON 형식으로 반환
result = {'message': pred_result}
return JsonResponse(result)
except Exception as e:
return JsonResponse({'message': 'Error: {}'.format(str(e))})
else:
return JsonResponse({'message': 'Invalid request method'})
urls.py
path('process_data/', views.process_data, name='process_data'), # "/process_data/" URL 패턴 추가
장고 실행 화면

예상가격이 리턴되는것을 확인할수 있다!!!

내일 최종적으로 쿠버플로우 파이프라인을 구축하고 장고를 올려보자!!!
파이프라인
모델을 돌리는 이미지( 스케일러 객체, 인코딩 객체 저장) >>> 카팁을 돌려 최적의 파라미터를 찾고 파싱해 모델에 적용시켜 모델을 저장시키는 이미지
총 2개의 모델이 돌아가야됨 레어아바타, 상급 아바타