Build a robust food delivery backend with Lovable. Follow our step-by-step guide to design a scalable, efficient system for seamless, reliable service.
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Project Setup and File Creation
main.py
. This file will contain all the backend code for our food delivery service.orders.json
in the project’s root directory. This file will act as a simple database to store orders. Open orders.json
and insert an empty JSON array:
[]
main.py
file to automatically install Flask (if not already installed):
import sys
try:
from flask import Flask, request, jsonify, abort
except ImportError:
import subprocess
subprocess.check\_call([sys.executable, "-m", "pip", "install", "flask"])
from flask import Flask, request, jsonify, abort
Setting Up the Backend Server and API Endpoints
main.py
, set up the Flask server and create helper functions for reading and writing orders. Insert this code below the dependency installation snippet:
import json
app = Flask(name)
def read_orders():
with open('orders.json', 'r') as f:
return json.load(f)
def write_orders(orders):
with open('orders.json', 'w') as f:
json.dump(orders, f)
@app.route('/order', methods=['POST'])
def create_order():
order = request.get_json()
orders = read_orders()
orders.append(order)
write_orders(orders)
return jsonify(order), 201
@app.route('/orders', methods=['GET'])
def get_orders():
orders = read_orders()
return jsonify(orders)
if name == 'main':
app.run(host='0.0.0.0', port=5000)
Incorporating Basic Authentication for Security
main.py
(for example, just after the previous endpoints):
from functools import wraps
def require_api_key(f):
@wraps(f)
def decorated(_args, _*kwargs):
if request.headers.get('x-api-key') != 'YOUR_API_KEY':
abort(401)
return f(_args, _*kwargs)
return decorated
@app.route('/secure_order', methods=['POST'])
@require_api_key
def secure_create_order():
order = request.get_json()
orders = read_orders()
orders.append(order)
write_orders(orders)
return jsonify(order), 201
YOUR_API_KEY
with a secret key of your choice.
Testing and Debugging Your Food Delivery Backend
5000
./order
with a JSON payload. For example, you can use Lovable’s HTTP request simulation feature or an external tool like Postman./orders
via a browser or API client to see the list of created orders./secure\_order
, ensure you include the header x-api-key
with the correct key in your request.
Deploying and Iterating on Your Backend
const express = require('express');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
mongoose.connect('mongodb://localhost:27017/fooddelivery', {
useNewUrlParser: true,
useUnifiedTopology: true
});
const OrderSchema = new mongoose.Schema({
restaurantId: { type: mongoose.Schema.Types.ObjectId, ref: 'Restaurant' },
items: [{
foodId: mongoose.Schema.Types.ObjectId,
quantity: Number
}],
status: {
type: String,
enum: ['pending', 'preparing', 'delivering', 'completed'],
default: 'pending'
},
createdAt: { type: Date, default: Date.now }
});
const Order = mongoose.model('Order', OrderSchema);
app.put('/api/orders/:id/status', async (req, res) => {
try {
const { status } = req.body;
if (!['pending', 'preparing', 'delivering', 'completed'].includes(status)) {
return res.status(400).json({ error: 'Invalid status value' });
}
const order = await Order.findByIdAndUpdate(
req.params.id,
{ status },
{ new: true }
);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
res.json(order);
} catch (err) {
res.status(500).json({ error: 'Server error' });
}
});
app.listen(3000, () => {
console.log('Food delivery backend running on port 3000');
});
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const MAPBOX_API_TOKEN = 'your_mapbox_api\_token';
app.get('/api/delivery/estimate', async (req, res) => {
try {
const { origin, destination } = req.query;
if (!origin || !destination) {
return res.status(400).json({ error: 'Both origin and destination coordinates are required in "longitude,latitude" format.' });
}
const url = `https://api.mapbox.com/directions/v5/mapbox/driving/${origin};${destination}?access_token=${MAPBOX_API_TOKEN}&geometries=geojson`;
const response = await axios.get(url);
if (response.data && response.data.routes && response.data.routes.length > 0) {
const { distance, duration } = response.data.routes[0];
return res.json({ distance, duration });
}
res.status(500).json({ error: 'Unable to retrieve route data' });
} catch (error) {
res.status(500).json({ error: 'Server error' });
}
});
app.listen(4000, () => {
console.log('Food delivery backend API is running on port 4000');
});
const express = require('express');
const mongoose = require('mongoose');
const app = express();
app.use(express.json());
const OrderSchema = new mongoose.Schema({
customerId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
items: [
{
restaurantId: { type: mongoose.Schema.Types.ObjectId, ref: 'Restaurant' },
foodId: { type: mongoose.Schema.Types.ObjectId, ref: 'Food' },
quantity: Number
}
],
status: {
type: String,
enum: ['pending', 'assigned', 'split', 'delivering', 'completed'],
default: 'pending'
},
createdAt: { type: Date, default: Date.now }
});
const Order = mongoose.model('Order', OrderSchema);
app.post('/api/orders/split', async (req, res) => {
try {
const { customerId, items } = req.body;
if (!customerId || !items || !Array.isArray(items) || items.length === 0) {
return res.status(400).json({ error: 'Invalid order data' });
}
// Group items by their restaurantId
const ordersByRestaurant = items.reduce((acc, item) => {
const key = item.restaurantId;
if (!acc[key]) {
acc[key] = [];
}
acc[key].push({
foodId: item.foodId,
quantity: item.quantity
});
return acc;
}, {});
// Create sub-orders for each restaurant
const createdOrders = [];
for (const restaurantId in ordersByRestaurant) {
const orderData = {
customerId,
items: ordersByRestaurant[restaurantId].map((item) => ({
restaurantId,
...item
})),
status: 'pending'
};
const subOrder = new Order(orderData);
await subOrder.save();
createdOrders.push(subOrder);
}
res.status(201).json({
message: 'Order has been split into sub-orders successfully.',
orders: createdOrders
});
} catch (error) {
res.status(500).json({ error: 'Server error while splitting order.' });
}
});
mongoose.connect('mongodb://localhost:27017/fooddelivery', {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
app.listen(5000, () => {
console.log('Food delivery backend running on port 5000');
});
})
.catch((err) => {
console.error('Database connection error:', err);
});
Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Planning the Food Delivery Backend System
Designing the System Architecture
Integrating AI Code Generators
# ai\_generator.py
def generate_endpoint_code(endpoint\_name, method):
# This is a stub function that an AI generator might help populate
code\_template = f'''
@app.route('/{endpoint\_name}', methods=['{method.upper()}'])
def {endpoint\_name}():
# Implement the {endpoint\_name} functionality
return jsonify({{"status": "success", "message": "Endpoint {endpoint\_name} reached"}})
'''
return code\_template
if name == 'main':
print(generate_endpoint_code("order", "post"))
Developing Backend Endpoints
from flask import Flask, request, jsonify
app = Flask(name)
@app.route('/create_order', methods=['POST'])
def create_order():
order_data = request.get_json()
# Validate and process the order data here
return jsonify({"status": "success", "order_id": 123})
if name == 'main':
app.run(host='0.0.0.0', port=5000)
Configuring the Database
from flask\_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
customer_id = db.Column(db.Integer, nullable=False)
restaurant_id = db.Column(db.Integer, nullable=False)
total_amount = db.Column(db.Float, nullable=False)
status = db.Column(db.String(50), default='Pending')
Implementing Security Best Practices
Testing and Debugging Using AI Tools
import pytest
from app import app
@pytest.fixture
def client():
app.testing = True
with app.test_client() as client:
yield client
def test_create_order(client):
response = client.post('/create_order', json={'customer_id': 1, 'restaurant_id': 2, 'total_amount': 29.99})
json_data = response.get_json()
assert json_data['status'] == 'success'
Deployment and Maintenance
# Dockerfile
FROM python:3.9-slim
WORK
When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.