Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions django-mongo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Inventory Management Application

## Overview

A simple Django + MongoDB inventory management application using mongoengine and Django REST Framework to test Keploy integration capabilities using Django and MongoDB.
The endpoints available will be:

1. `GET /api/items/` - List all items
2. `POST /api/items/` - Create a new item
3. `GET /api/items/<id>/` - Retrieve an item by ID
4. `PUT /api/items/<id>/` - Update an item by ID
5. `DELETE /api/items/<id>/` - Delete an item by ID

## Requirements

- Python 3.x
- Django
- mongoengine
- djangorestframework

## Setup Instructions

1. Clone the repository and navigate to project directory.
```bash
git clone https://github.com/keploy/samples-python.git
cd samples-python/django-mongo/django_mongo
```
2. Install Keploy.
```bash
curl --silent -O -L https://keploy.io/install.sh && source install.sh
```
3. Start MongoDB instance.
```bash
docker pull mongo
docker run --name mongodb -d -p 27017:27017 -v mongo_data:/data/db -e MONGO_INITDB_ROOT_USERNAME=<username> -e MONGO_INITDB_ROOT_PASSWORD=<password> mongo
```
4. Set up Django appllication.
```bash
python3 -m virtualenv venv
source venv/bin/activate
pip3 install -r requirements.txt
```
5. Capture the testcases.
```bash
keploy record -c "python3 manage.py runserver"
```
6. Generate testcases by making API calls.
```bash
# List items
# GET /api/items/
curl -X GET http://localhost:8000/api/items/
```
```bash
# Create Item
# POST /api/items/
curl -X POST http://localhost:8000/api/items/ \
-H "Content-Type: application/json" \
-d '{
"name": "Gadget C",
"quantity": 200,
"description": "A versatile gadget with numerous features."
}'
```
```bash
# Retrieve Item
# GET /api/items/<id>/
curl -X GET http://localhost:8000/api/items/<id>/
```
```bash
# Update Item
# PUT /api/items/<id>/
curl -X PUT http://localhost:8000/api/items/6142d21e122bda15f6f87b1d/ \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Widget A",
"quantity": 120,
"description": "An updated description for Widget A."
}'
```
```bash
# Delete Item
# DELETE /api/items/<id>/
curl -X DELETE http://localhost:8000/api/items/<id>/
```
Replace `<id>` with the actual ID of the item you want to retrieve, update, or delete.

## Run the testcases

Shut down MongoDB, Keploy doesn't need it during tests.
```bash
keploy test -c "python3 manage.py runserver" --delay 10
```
Empty file.
16 changes: 16 additions & 0 deletions django-mongo/django_mongo/django_mongo/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for django_mongo project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_mongo.settings')

application = get_asgi_application()
148 changes: 148 additions & 0 deletions django-mongo/django_mongo/django_mongo/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
"""
Django settings for django_mongo project.

Generated by 'django-admin startproject' using Django 5.1.2.

For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/ref/settings/
"""

from pathlib import Path
import mongoengine

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-3g@-x5(3t(i(p^qnu9lz3hk1u1yobrvwz($5^ucvnn0a6b$%ob'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'inventory',
]

REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
}

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'django_mongo.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

WSGI_APPLICATION = 'django_mongo.wsgi.application'


# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases

# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }


# Password validation
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]


# Internationalization
# https://docs.djangoproject.com/en/5.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# MongoDB configuration
MONGO_DB_NAME = 'inventory_db'
MONGO_USER = 'admin'
MONGO_PASSWORD = 'admin'
MONGO_HOST = 'localhost'
MONGO_PORT = 27017

# Connect to MongoDB
mongoengine.connect(
db=MONGO_DB_NAME,
username=MONGO_USER,
password=MONGO_PASSWORD,
host=MONGO_HOST,
port=MONGO_PORT
)
23 changes: 23 additions & 0 deletions django-mongo/django_mongo/django_mongo/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
URL configuration for django_mongo project.

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('inventory.urls')),
]
16 changes: 16 additions & 0 deletions django-mongo/django_mongo/django_mongo/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
WSGI config for django_mongo project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_mongo.settings')

application = get_wsgi_application()
Empty file.
3 changes: 3 additions & 0 deletions django-mongo/django_mongo/inventory/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions django-mongo/django_mongo/inventory/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class InventoryConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'inventory'
Empty file.
7 changes: 7 additions & 0 deletions django-mongo/django_mongo/inventory/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.db import models
from mongoengine import Document, StringField, IntField

class Item(Document):
name = StringField(required=True)
quantity = IntField(required=True)
description = StringField()
18 changes: 18 additions & 0 deletions django-mongo/django_mongo/inventory/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from rest_framework import serializers
from .models import Item

class ItemSerializer(serializers.Serializer):
id = serializers.CharField(read_only=True)
name = serializers.CharField(required=True)
quantity = serializers.IntegerField(required=True)
description = serializers.CharField(required=False)

def create(self, validated_data):
return Item(**validated_data).save()

def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.quantity = validated_data.get('quantity', instance.quantity)
instance.description = validated_data.get('description', instance.description)
instance.save()
return instance
3 changes: 3 additions & 0 deletions django-mongo/django_mongo/inventory/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
7 changes: 7 additions & 0 deletions django-mongo/django_mongo/inventory/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path
from .views import ItemViewSet

urlpatterns = [
path('items/', ItemViewSet.as_view({'get': 'list', 'post': 'create'})),
path('items/<str:pk>/', ItemViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
Loading