Skip to content

Commit f9eef6f

Browse files
Implement Mentor API with CRUD operations
This file implements a Django REST API for managing mentors, including CRUD operations, pagination, and custom validation.
1 parent 037bf0d commit f9eef6f

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

core/models.py

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
"""
2+
µLearn Backend – Mentor API Module
3+
---------------------------------
4+
Author: @anjanarajesh-00
5+
License: MIT
6+
Description:
7+
A fully featured Django REST API for managing mentors within µLearn.
8+
This module provides CRUD operations, validation, filtering,
9+
searching, sorting, and pagination. Written for clarity and reusability.
10+
11+
You can integrate this directly into your µLearn backend.
12+
"""
13+
14+
# ======================================================
15+
# Imports
16+
# ======================================================
17+
from django.db import models
18+
from rest_framework import serializers, generics, status, filters
19+
from rest_framework.response import Response
20+
from django.urls import path
21+
from rest_framework.pagination import PageNumberPagination
22+
23+
# ======================================================
24+
# Model: Mentor
25+
# ======================================================
26+
class Mentor(models.Model):
27+
"""
28+
Mentor model defines the core structure of a mentor in µLearn.
29+
Each mentor has a name, area of expertise, contact details,
30+
and optional profile information for community discovery.
31+
"""
32+
33+
# Basic Info
34+
name = models.CharField(max_length=100, help_text="Full name of the mentor")
35+
expertise = models.CharField(max_length=150, help_text="Primary area of expertise")
36+
37+
# Contact Info
38+
email = models.EmailField(unique=True, help_text="Email address (must be unique)")
39+
linkedin = models.URLField(blank=True, null=True, help_text="LinkedIn profile URL")
40+
41+
# Additional Info
42+
bio = models.TextField(blank=True, null=True, help_text="Short biography or background")
43+
available = models.BooleanField(default=True, help_text="Mentor availability status")
44+
created_at = models.DateTimeField(auto_now_add=True)
45+
updated_at = models.DateTimeField(auto_now=True)
46+
47+
def __str__(self):
48+
return f"{self.name} ({self.expertise})"
49+
50+
class Meta:
51+
ordering = ['name']
52+
verbose_name = "Mentor"
53+
verbose_name_plural = "Mentors"
54+
55+
56+
# ======================================================
57+
# Serializer: MentorSerializer
58+
# ======================================================
59+
class MentorSerializer(serializers.ModelSerializer):
60+
"""
61+
Converts Mentor model instances to JSON and validates input data.
62+
"""
63+
64+
class Meta:
65+
model = Mentor
66+
fields = [
67+
'id',
68+
'name',
69+
'expertise',
70+
'email',
71+
'linkedin',
72+
'bio',
73+
'available',
74+
'created_at',
75+
'updated_at',
76+
]
77+
78+
# Custom validation example
79+
def validate_name(self, value):
80+
if len(value.split()) < 2:
81+
raise serializers.ValidationError("Please enter full name (first and last).")
82+
return value
83+
84+
def validate_expertise(self, value):
85+
if len(value) < 3:
86+
raise serializers.ValidationError("Expertise must have at least 3 characters.")
87+
return value
88+
89+
90+
# ======================================================
91+
# Pagination Class
92+
# ======================================================
93+
class MentorPagination(PageNumberPagination):
94+
"""
95+
Custom pagination for mentor list.
96+
"""
97+
page_size = 5
98+
page_size_query_param = 'page_size'
99+
max_page_size = 20
100+
101+
102+
# ======================================================
103+
# Views
104+
# ======================================================
105+
106+
class MentorListCreateView(generics.ListCreateAPIView):
107+
"""
108+
View to list all mentors or create a new one.
109+
Includes filtering, search, and ordering capabilities.
110+
"""
111+
queryset = Mentor.objects.all()
112+
serializer_class = MentorSerializer
113+
pagination_class = MentorPagination
114+
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
115+
search_fields = ['name', 'expertise', 'bio']
116+
ordering_fields = ['name', 'created_at']
117+
118+
def create(self, request, *args, **kwargs):
119+
"""
120+
Overridden create method to return a custom success message.
121+
"""
122+
serializer = self.get_serializer(data=request.data)
123+
serializer.is_valid(raise_exception=True)
124+
self.perform_create(serializer)
125+
headers = self.get_success_headers(serializer.data)
126+
return Response(
127+
{
128+
"message": "🎉 Mentor successfully added!",
129+
"mentor": serializer.data
130+
},
131+
status=status.HTTP_201_CREATED,
132+
headers=headers,
133+
)
134+
135+
136+
class MentorDetailView(generics.RetrieveUpdateDestroyAPIView):
137+
"""
138+
Retrieve, update, or delete a specific mentor by ID.
139+
"""
140+
queryset = Mentor.objects.all()
141+
serializer_class = MentorSerializer
142+
143+
def delete(self, request, *args, **kwargs):
144+
instance = self.get_object()
145+
self.perform_destroy(instance)
146+
return Response({"message": "🗑️ Mentor deleted successfully"}, status=status.HTTP_200_OK)
147+
148+
149+
# ======================================================
150+
# Extra Feature: Mentor Availability Toggle
151+
# ======================================================
152+
from rest_framework.decorators import api_view
153+
154+
@api_view(['POST'])
155+
def toggle_availability(request, pk):
156+
"""
157+
Endpoint to toggle the mentor's availability status.
158+
"""
159+
try:
160+
mentor = Mentor.objects.get(pk=pk)
161+
except Mentor.DoesNotExist:
162+
return Response({"error": "Mentor not found"}, status=status.HTTP_404_NOT_FOUND)
163+
164+
mentor.available = not mentor.available
165+
mentor.save()
166+
return Response({
167+
"message": f"Mentor '{mentor.name}' availability updated to {mentor.available}",
168+
"available": mentor.available,
169+
})
170+
171+
172+
# ======================================================
173+
# URL Configuration
174+
# ======================================================
175+
urlpatterns = [
176+
path('mentors/', MentorListCreateView.as_view(), name='mentor-list'),
177+
path('mentors/<int:pk>/', MentorDetailView.as_view(), name='mentor-detail'),
178+
path('mentors/<int:pk>/toggle/', toggle_availability, name='mentor-toggle'),
179+
]
180+
181+
182+
# ======================================================
183+
# How to Integrate This File
184+
# ======================================================
185+
"""
186+
Integration Steps:
187+
188+
1️⃣ Place this file in your main Django app (example: core/)
189+
Path: mulearn-backend/core/mentor_api.py
190+
191+
2️⃣ In your project’s main urls.py, import and include these URLs:
192+
from core.mentor_api import urlpatterns as mentor_urls
193+
urlpatterns += mentor_urls
194+
195+
3️⃣ Apply migrations:
196+
python manage.py makemigrations
197+
python manage.py migrate
198+
199+
4️⃣ Run the server:
200+
python manage.py runserver
201+
202+
5️⃣ Test the API:
203+
GET /mentors/ → List mentors
204+
POST /mentors/ → Add new mentor
205+
GET /mentors/<id>/ → Get mentor details
206+
PUT /mentors/<id>/ → Update mentor
207+
DELETE /mentors/<id>/ → Delete mentor
208+
POST /mentors/<id>/toggle/ → Toggle availability
209+
210+
✅ Example JSON for adding a mentor:
211+
{
212+
"name": "Anjana Rajesh",
213+
"expertise": "AI & Backend Development",
214+
"email": "anjana@example.com",
215+
"linkedin": "https://linkedin.com/in/anjanarajesh",
216+
"bio": "Passionate mentor focusing on AI-driven learning tools",
217+
"available": true
218+
}
219+
220+
🎯 Expected Output:
221+
{
222+
"message": "🎉 Mentor successfully added!",
223+
"mentor": {
224+
"id": 1,
225+
"name": "Anjana Rajesh",
226+
"expertise": "AI & Backend Development",
227+
"email": "anjana@example.com",
228+
"linkedin": "https://linkedin.com/in/anjanarajesh",
229+
"bio": "Passionate mentor focusing on AI-driven learning tools",
230+
"available": true,
231+
"created_at": "2025-10-30T18:32:00Z",
232+
"updated_at": "2025-10-30T18:32:00Z"
233+
}
234+
}
235+
"""
236+
237+
# ======================================================
238+
# End of File
239+
# ======================================================

0 commit comments

Comments
 (0)