Building a Mock Server with Python, Django, MySQL, Redis, and Vue
This guide explains how to create a full‑stack mock server using Python, Django, MySQL, Redis, and Vue, covering database setup, REST API implementation, Redis caching, and a Vue front‑end for managing mock data, enabling efficient automated testing and development.
Mock servers simulate backend responses, allowing automated tests and development to run without a real server, improving efficiency, reducing cost, and fostering tighter front‑end/back‑end collaboration.
First, create a MySQL database and a mock table to store mock data:
CREATE DATABASE mockdb;</code>
<code>USE mockdb;</code>
<code>CREATE TABLE mock (</code>
<code> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,</code>
<code> url VARCHAR(255) NOT NULL,</code>
<code> method VARCHAR(10) NOT NULL,</code>
<code> request_body TEXT,</code>
<code> response_body TEXT</code>
<code>);Next, implement a Django REST API to add, delete, update, and retrieve mock entries. The key files are:
# urls.py
from django.urls import path
from .views import MockList, MockDetail
urlpatterns = [
path('mocks/', MockList.as_view()),
path('mocks/<int:pk>/', MockDetail.as_view()),
] # views.py
from rest_framework import generics
from .models import Mock
from .serializers import MockSerializer
class MockList(generics.ListCreateAPIView):
queryset = Mock.objects.all()
serializer_class = MockSerializer
class MockDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Mock.objects.all()
serializer_class = MockSerializer # models.py
from django.db import models
class Mock(models.Model):
url = models.CharField(max_length=255)
method = models.CharField(max_length=10)
request_body = models.TextField(blank=True)
response_body = models.TextField()
def __str__(self):
return f"{self.method} {self.url}" # serializers.py
from rest_framework import serializers
from .models import Mock
class MockSerializer(serializers.ModelSerializer):
class Meta:
model = Mock
fields = '__all__'To speed up lookups, a Redis‑based service caches mock responses. The service class uses Django settings for connection details and synchronizes data between MySQL and Redis:
# mock.py
import json, redis, requests
from django.conf import settings
from .models import Mock
class MockService:
def __init__(self):
self.r = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB)
self.mock_api = f"http://{settings.API_HOST}/api/mocks/"
def add_mock(self, url, method, request_body, response_body):
mock = Mock.objects.create(url=url, method=method, request_body=request_body, response_body=response_body)
self.r.hset('mocks', f"{method}:{url}", json.dumps({'response_body': response_body}))
return requests.post(self.mock_api, data={'url': url, 'method': method, 'request_body': request_body, 'response_body': response_body})
# remove_mock, update_mock, get_mock_response methods omitted for brevityFinally, a Vue component (using Element‑UI) provides a UI for managing mock entries. It displays a table of mocks and a dialog for creating or editing records, communicating with the Django API via Axios:
<!-- Vue.js Mock Component -->
<template>
<div>
<el-table :data="mocks">
<el-table-column label="URL"><template slot-scope="scope"><span>{{ scope.row.url }}</span></template></el-table-column>
<el-table-column label="Method"><template slot-scope="scope"><span>{{ scope.row.method }}</span></template></el-table-column>
<el-table-column label="Request Body"><template slot-scope="scope"><span>{{ scope.row.request_body }}</span></template></el-table-column>
<el-table-column label="Response Body"><template slot-scope="scope"><span>{{ scope.row.response_body }}</span></template></el-table-column>
<el-table-column label="Actions">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="small" @click="editMock(scope.row)">Edit</el-button>
<el-popover placement="top-start" width="200" trigger="click" v-model="deletePopoverVisible[scope.$index]">
<p>Are you sure to delete this mock?</p>
<div style="text-align: right; margin: 0">
<el-button type="text" size="small" @click="deletePopoverVisible[scope.$index] = false">Cancel</el-button>
<el-button type="primary" size="small" @click="deleteMock(scope.row, scope.$index)">OK</el-button>
</div>
<el-button slot="reference" type="primary" icon="el-icon-delete" size="small">Delete</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<el-dialog title="New Mock" :visible.sync="mockVisible" width="50%">
<el-form :model="mockForm" ref="mockForm">
<el-form-item label="URL" :label-width="formLabelWidth"><el-input v-model="mockForm.url" placeholder="Enter URL"></el-input></el-form-item>
<el-form-item label="Method" :label-width="formLabelWidth">
<el-radio-group v-model="mockForm.method">
<el-radio-button label="GET">GET</el-radio-button>
<el-radio-button label="POST">POST</el-radio-button>
<el-radio-button label="PUT">PUT</el-radio-button>
<el-radio-button label="DELETE">DELETE</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="Request Body" :label-width="formLabelWidth"><el-input v-model="mockForm.request_body" placeholder="Enter request body"></el-input></el-form-item>
<el-form-item label="Response Body" :label-width="formLabelWidth"><el-input v-model="mockForm.response_body" placeholder="Enter response body"></el-input></el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="mockVisible = false">Cancel</el-button>
<el-button type="primary" @click="saveMock">Save</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
mocks: [],
mockForm: {url: '', method: 'GET', request_body: '', response_body: ''},
formLabelWidth: '120px',
mockVisible: false,
deletePopoverVisible: []
}
},
methods: {
loadMocks() { axios.get('/api/mocks/').then(r => { this.mocks = r.data }).catch(console.log) },
addMock(url, method, request_body, response_body) { axios.post('/api/mocks/', {url, method, request_body, response_body}).then(r => { this.mocks.push(r.data) }).catch(console.log) },
removeMock(id, index) { axios.delete(`/api/mocks/${id}/`).then(() => { this.mocks.splice(index, 1) }).catch(console.log) },
updateMock(id, url, method, request_body, response_body) { axios.put(`/api/mocks/${id}/`, {url, method, request_body, response_body}).then(r => { const i = this.mocks.findIndex(m => m.id === id); this.mocks.splice(i, 1, r.data) }).catch(console.log) },
editMock(mock) { this.mockForm = Object.assign({}, mock); this.mockVisible = true },
saveMock() { const {url, method, request_body, response_body} = this.mockForm; if (url && response_body) { const i = this.mocks.findIndex(m => m.id === this.mockForm.id); if (i !== -1) this.updateMock(this.mockForm.id, url, method, request_body, response_body); else this.addMock(url, method, request_body, response_body); this.mockVisible = false; this.mockForm = {url: '', method: 'GET', request_body: '', response_body: ''} } },
deleteMock(mock, index) { this.removeMock(mock.id, index); this.deletePopoverVisible.splice(index, 1) }
},
mounted() { this.loadMocks() }
}
</script>By combining the Python/Django backend, MySQL storage, Redis caching, and the Vue front‑end, you obtain a complete mock service that can be used in automated tests or during development to quickly simulate API responses.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
