React의 셀러리 진행률 표시줄
27937 단어 reactreduxdjangojavascript
2. Backend setup
3. Frontend setup
1. 개요
The progress bar is one of the most useful UI components for tracking the actual progress of the task. But It is still a complex task to track the exact progress. In this tutorial, I will guide you to make the progress bar using celery-progress
반응이 있는 라이브러리.
Please check Celery Progress Bars for Django before starting this tutorial.
이 튜토리얼에서는 DRF(Django Rest Framework)를 사용하여 데이터를 서버에 업로드하고 서버에서 데이터를 사전 처리한 다음 응답을 다시 보낼 것입니다. 필자의 경우 데이터 전처리에 2-3분이 소요되므로 react를 사용하여 프론트엔드에서 처리 진행률 표시줄을 시각화하겠습니다.
2. 백엔드 설정
I consider you already set up your Django with celery . 이제 pip를 사용하여 celery-progress
라이브러리를 설치해야 합니다.
pip install celery-progress
celery-progress in urls.py
파일에 끝점 URL을 추가합니다.
from django.urls import re_path, include
re_path(r'^celery-progress/', include('celery_progress.urls')),
예제 함수를 celery_function
로 작성하고 있습니다. 실제 진행률 추적기 기능을 교체해야 합니다.
from celery import shared_task
from celery_progress.backend import ProgressRecorder
import time
@shared_task(bind=True)
def celery_function(self, seconds):
progress_recorder = ProgressRecorder(self)
result = 0
for i in range(seconds):
time.sleep(1)
result += i
progress_recorder.set_progress(i + 1, seconds)
return result
다음과 같은 Data
모델이 있습니다.
class Data(models.Model):
name = models.CharField(max_length=100)
taskId = models.CharField(max_length=200, blank=True)
...
...
...
이제 DRF의 create
클래스에서 ViewSet
메서드를 덮어쓰고 celery_function.delay(time)
함수를 호출합니다.
In my code, my model name is Data
, the serializer class is DataSerializer
. I used the patch
method to append the task_id to the Data model.
class DataViewSet(viewsets.ModelViewSet):
queryset = Data.objects.all()
serializer_class = DataSerializer
permission_classes = [permissions.IsAuthenticated]
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
if serializer.is_valid():
data = serializer.data
id = data['id']
task = celery_function.delay(10)
self.patch(id, {"taskId": task.id})
return Response({'task_id': task.id}, status=status.HTTP_201_CREATED)
def patch(self, pk, taskid):
instance = self.get_object(pk)
serializer = DataSerializer(
instance, data=taskid, partial=True)
if serializer.is_valid():
serializer.save()
우리는 백엔드에서 모든 것을 설정했습니다. 작업 진행 상황은 다음 URL에서 확인할 수 있습니다. http://localhost:8000/celery-progress/${task_id} .
3. 프론트엔드 설정
In the frontend, I am going to write the custom progress bar using react-bootstrap
. The DRF backend will provide us the task progress in this URL: http://localhost:8000/celery-progress/${task_id} . 이제 작업 상태가 완료로 변경될 때까지 이 URL을 재귀적으로 적중해야 합니다. 이를 위해 axios
을 사용하여 진행 상황을 가져옵니다.
이 튜토리얼에서는 react-redux 을 사용하고 있습니다. reduxactions.js
파일에서 두 개의 함수를 만들었습니다. 하나는 데이터를 추가하는 함수(addData
)이고 다른 하나는 작업 진행 상황을 가져오는 함수(getProgress
)입니다. addData
함수는 서버에 데이터를 추가할 때만 유용합니다.
export const addData = (data) => (dispatch, getState) => {
axios
.post(`http://localhost:8000/api/data/`, data)
.then((res) => {
dispatch({
type: ADD_DATA,
payload: res.data,
});
const task_id = res.data?.task_id;
dispatch(getProgress(task_id));
})
.catch((err) =>
console.log(err)
);
};
getProgress
는 JSON
응답으로 작업의 실제 진행 상황을 가져옵니다. json 응답의 예는 아래와 같습니다.
{"complete": true, "success": true, "progress": {"pending": false, "current": 100, "total": 100, "percent": 100}, "result": "Done"}
여기에서 getProgress
함수를 재귀적으로 호출하여 작업이 완료될 때까지 현재 진행 상황을 가져옵니다.
export const getProgress = (taskId) => {
return (dispatch) => {
return axios
.get(`http://localhost:8000/celery-progress/${taskId}`)
.then((res) => {
dispatch({
type: PROGRESS_BAR,
payload: { taskid: taskId, ...res.data },
});
if (!res.data.complete && !res.data?.progess?.pending) {
return dispatch(getProgress(taskId));
}
})
.catch((err) =>
console.log(err)
);
};
};
또한 reduxreducers.js
파일에 다음과 같이 응답을 추가했습니다.
import { ADD_DATA, PROGRESS_BAR } from "../actions/types";
const initialState = {
progress: {},
data: [],
};
export default function (state = initialState, action) {
switch (action.type) {
case PROGRESS_BAR:
return {
...state,
progress: action.payload,
};
case ADD_DATA:
return {
...state,
data: action.payload,
};
default:
return state;
}
}
이제 아래와 같이 진행률 표시줄을 시각화하는 반응 구성 요소를 작성해 보겠습니다.
import React, { Component } from "react";
import { connect } from "react-redux";
import { ProgressBar } from "react-bootstrap";
class ProgressBarUi extends Component {
render() {
const { percent } = this.props;
return (
<ProgressBar
now={percent}
animated
variant="success"
label={`${percent}%`}
/>
);
}
}
export default ProgressBarUi;
진행률 표시줄은 진행 상황이 완료되지 않고 보류 중이 아닌 경우에만 시각화해야 합니다.
import React, { Component } from "react";
import { connect } from "react-redux";
import { addData } from "../../../actions";
import ProgressBarUi from "../../common/ProgressBar";
class AddData extends Component {
onSubmit = (e) => {
const data = {
key1: "value1",
key2: "value2",
};
this.props.addExposure(data);
};
render() {
const { progress } = this.props;
return (
<div>
{/* your progress bar goes here */}
{progress?.progress && !progress?.complete && (
<ProgressBarUi percent={progress.progress?.percent} />
)}
...
...
...
{/* data submit button */}
<input type="submit" value="Add data" onSubmit={this.onSubmit} />
</div>
);
}
}
const mapStateToProps = (state) => ({
progress: state.progress,
});
export default connect(mapStateToProps, {
addData,
})(AddData);
자, 마침내 Django, react, celery를 사용하여 진행률 표시줄을 성공적으로 설정했습니다.
Reference
이 문제에 관하여(React의 셀러리 진행률 표시줄), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/iamtekson/celery-task-progress-bar-in-react-4ane
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Please check Celery Progress Bars for Django before starting this tutorial.
celery-progress
라이브러리를 설치해야 합니다.pip install celery-progress
celery-progress in
urls.py
파일에 끝점 URL을 추가합니다.from django.urls import re_path, include
re_path(r'^celery-progress/', include('celery_progress.urls')),
예제 함수를
celery_function
로 작성하고 있습니다. 실제 진행률 추적기 기능을 교체해야 합니다.from celery import shared_task
from celery_progress.backend import ProgressRecorder
import time
@shared_task(bind=True)
def celery_function(self, seconds):
progress_recorder = ProgressRecorder(self)
result = 0
for i in range(seconds):
time.sleep(1)
result += i
progress_recorder.set_progress(i + 1, seconds)
return result
다음과 같은
Data
모델이 있습니다.class Data(models.Model):
name = models.CharField(max_length=100)
taskId = models.CharField(max_length=200, blank=True)
...
...
...
이제 DRF의
create
클래스에서 ViewSet
메서드를 덮어쓰고 celery_function.delay(time)
함수를 호출합니다.In my code, my model name is
Data
, the serializer class isDataSerializer
. I used thepatch
method to append the task_id to the Data model.
class DataViewSet(viewsets.ModelViewSet):
queryset = Data.objects.all()
serializer_class = DataSerializer
permission_classes = [permissions.IsAuthenticated]
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
if serializer.is_valid():
data = serializer.data
id = data['id']
task = celery_function.delay(10)
self.patch(id, {"taskId": task.id})
return Response({'task_id': task.id}, status=status.HTTP_201_CREATED)
def patch(self, pk, taskid):
instance = self.get_object(pk)
serializer = DataSerializer(
instance, data=taskid, partial=True)
if serializer.is_valid():
serializer.save()
우리는 백엔드에서 모든 것을 설정했습니다. 작업 진행 상황은 다음 URL에서 확인할 수 있습니다. http://localhost:8000/celery-progress/${task_id} .
3. 프론트엔드 설정
In the frontend, I am going to write the custom progress bar using react-bootstrap
. The DRF backend will provide us the task progress in this URL: http://localhost:8000/celery-progress/${task_id} . 이제 작업 상태가 완료로 변경될 때까지 이 URL을 재귀적으로 적중해야 합니다. 이를 위해 axios
을 사용하여 진행 상황을 가져옵니다.
이 튜토리얼에서는 react-redux 을 사용하고 있습니다. reduxactions.js
파일에서 두 개의 함수를 만들었습니다. 하나는 데이터를 추가하는 함수(addData
)이고 다른 하나는 작업 진행 상황을 가져오는 함수(getProgress
)입니다. addData
함수는 서버에 데이터를 추가할 때만 유용합니다.
export const addData = (data) => (dispatch, getState) => {
axios
.post(`http://localhost:8000/api/data/`, data)
.then((res) => {
dispatch({
type: ADD_DATA,
payload: res.data,
});
const task_id = res.data?.task_id;
dispatch(getProgress(task_id));
})
.catch((err) =>
console.log(err)
);
};
getProgress
는 JSON
응답으로 작업의 실제 진행 상황을 가져옵니다. json 응답의 예는 아래와 같습니다.
{"complete": true, "success": true, "progress": {"pending": false, "current": 100, "total": 100, "percent": 100}, "result": "Done"}
여기에서 getProgress
함수를 재귀적으로 호출하여 작업이 완료될 때까지 현재 진행 상황을 가져옵니다.
export const getProgress = (taskId) => {
return (dispatch) => {
return axios
.get(`http://localhost:8000/celery-progress/${taskId}`)
.then((res) => {
dispatch({
type: PROGRESS_BAR,
payload: { taskid: taskId, ...res.data },
});
if (!res.data.complete && !res.data?.progess?.pending) {
return dispatch(getProgress(taskId));
}
})
.catch((err) =>
console.log(err)
);
};
};
또한 reduxreducers.js
파일에 다음과 같이 응답을 추가했습니다.
import { ADD_DATA, PROGRESS_BAR } from "../actions/types";
const initialState = {
progress: {},
data: [],
};
export default function (state = initialState, action) {
switch (action.type) {
case PROGRESS_BAR:
return {
...state,
progress: action.payload,
};
case ADD_DATA:
return {
...state,
data: action.payload,
};
default:
return state;
}
}
이제 아래와 같이 진행률 표시줄을 시각화하는 반응 구성 요소를 작성해 보겠습니다.
import React, { Component } from "react";
import { connect } from "react-redux";
import { ProgressBar } from "react-bootstrap";
class ProgressBarUi extends Component {
render() {
const { percent } = this.props;
return (
<ProgressBar
now={percent}
animated
variant="success"
label={`${percent}%`}
/>
);
}
}
export default ProgressBarUi;
진행률 표시줄은 진행 상황이 완료되지 않고 보류 중이 아닌 경우에만 시각화해야 합니다.
import React, { Component } from "react";
import { connect } from "react-redux";
import { addData } from "../../../actions";
import ProgressBarUi from "../../common/ProgressBar";
class AddData extends Component {
onSubmit = (e) => {
const data = {
key1: "value1",
key2: "value2",
};
this.props.addExposure(data);
};
render() {
const { progress } = this.props;
return (
<div>
{/* your progress bar goes here */}
{progress?.progress && !progress?.complete && (
<ProgressBarUi percent={progress.progress?.percent} />
)}
...
...
...
{/* data submit button */}
<input type="submit" value="Add data" onSubmit={this.onSubmit} />
</div>
);
}
}
const mapStateToProps = (state) => ({
progress: state.progress,
});
export default connect(mapStateToProps, {
addData,
})(AddData);
자, 마침내 Django, react, celery를 사용하여 진행률 표시줄을 성공적으로 설정했습니다.
Reference
이 문제에 관하여(React의 셀러리 진행률 표시줄), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/iamtekson/celery-task-progress-bar-in-react-4ane
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
export const addData = (data) => (dispatch, getState) => {
axios
.post(`http://localhost:8000/api/data/`, data)
.then((res) => {
dispatch({
type: ADD_DATA,
payload: res.data,
});
const task_id = res.data?.task_id;
dispatch(getProgress(task_id));
})
.catch((err) =>
console.log(err)
);
};
{"complete": true, "success": true, "progress": {"pending": false, "current": 100, "total": 100, "percent": 100}, "result": "Done"}
export const getProgress = (taskId) => {
return (dispatch) => {
return axios
.get(`http://localhost:8000/celery-progress/${taskId}`)
.then((res) => {
dispatch({
type: PROGRESS_BAR,
payload: { taskid: taskId, ...res.data },
});
if (!res.data.complete && !res.data?.progess?.pending) {
return dispatch(getProgress(taskId));
}
})
.catch((err) =>
console.log(err)
);
};
};
import { ADD_DATA, PROGRESS_BAR } from "../actions/types";
const initialState = {
progress: {},
data: [],
};
export default function (state = initialState, action) {
switch (action.type) {
case PROGRESS_BAR:
return {
...state,
progress: action.payload,
};
case ADD_DATA:
return {
...state,
data: action.payload,
};
default:
return state;
}
}
import React, { Component } from "react";
import { connect } from "react-redux";
import { ProgressBar } from "react-bootstrap";
class ProgressBarUi extends Component {
render() {
const { percent } = this.props;
return (
<ProgressBar
now={percent}
animated
variant="success"
label={`${percent}%`}
/>
);
}
}
export default ProgressBarUi;
import React, { Component } from "react";
import { connect } from "react-redux";
import { addData } from "../../../actions";
import ProgressBarUi from "../../common/ProgressBar";
class AddData extends Component {
onSubmit = (e) => {
const data = {
key1: "value1",
key2: "value2",
};
this.props.addExposure(data);
};
render() {
const { progress } = this.props;
return (
<div>
{/* your progress bar goes here */}
{progress?.progress && !progress?.complete && (
<ProgressBarUi percent={progress.progress?.percent} />
)}
...
...
...
{/* data submit button */}
<input type="submit" value="Add data" onSubmit={this.onSubmit} />
</div>
);
}
}
const mapStateToProps = (state) => ({
progress: state.progress,
});
export default connect(mapStateToProps, {
addData,
})(AddData);
Reference
이 문제에 관하여(React의 셀러리 진행률 표시줄), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/iamtekson/celery-task-progress-bar-in-react-4ane텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)