In this we are going to learn how can we select existing objects in drf when we using post method or create objects using drf api.
Step 01: Project Initiated
Create new django project using shell
Command:
django-admin startproject maintain_proj
e.g .
PS:> django-admin startproject myproject
now we going to our created project root dir using our current shell
with this command
Command:
cd maintain_proj
e.g.
PS:> cd myproject
and we are going to install drf to our project and setup it.
Command:
pip install django-rest-framework
e.g.
PS:> cd myproject
now going to settings.py file for your root project in out case its
maintain_proj/
maintain_proj/
settings.py
Inside this file we are going to configure our drf here with basic setup none auth right now we setup auth in last.
Step02: Make webapps
Now we are going to create new webapp name "core" inside our "maintain_proj" djangoproject using our shell.
Command:
python -m startapp core
e.g.
PS:> python -m startapp core
or
django-admin startapp core
e.g.
PS:> django-admin startapp core
Step03: Create Models inside "core"
maintain_proj/
core/
models.py
Code:
from django.contrib.auth.models import User
import uuid
class Project(models.Model):
project_id = models.CharField(max_length=255, default=uuid.uuid4().hex[:12], editable=False)
project_name = models.CharField(max_length=50,blank=False)
description = models.TextField(blank=False,max_length=540)
started_at = models.DateField(blank=True,null=True)
end_at = models.DateField(blank=True,null=True)
created_at = models.DateTimeField(blank=True,auto_now_add=True)
#auto_now_add for automatic add firsttime when it object created so it not change even how many time we
updated_at = models.DateTimeField(blank=True,auto_now=True)
#auto_now is for whenever this we chnage anything in object it will update the date time and store it to updated_at
def __str__(self):
return f"{self.project_name},{self.project_id}"
class TimeSheet(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
projects = models.ManyToManyField(Project,blank=True)
week_start_date = models.DateField(blank=True,null=True)
hours_worked = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return f"{self.id}{self.user.username}"
We are here going to create two models and we are selection multiple objects from models1 to and connect them to new object of model2 object using m2m manytomanyfield.
e.g.
class Model_1(models.Model):
......
#M2M Fields Models:
class Model_2(models.Model):
field_name = ManytoManyField(Model1)
...........
Step04: Making API ENDPOINTS and Serializer,Views
Create new "api" folder/dir inside project root directory .
Inside the maintain_proj
maintain_proj/
api/
Inside this "api" first create a init file - __init__.py
4.1 : Now create new "serializers.py" file
Open this file and put this code on this file.
from rest_framework import serializers
from core.models import Project , TimeSheet
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = "__all__"
class TimeSheetSerializer(serializers.ModelSerializer):
projects = ProjectSerializer(many=True)
class Meta:
model = TimeSheet
fields = ['id','projects','user','week_start_date','hours_worked']
4.2: Now create "views.py" file and put this code on that
from rest_framework import generics
from core.models import Project, TimeSheet
from .serializers import ProjectSerializer,TimeSheetSerializer
from django.contrib.auth.models import User
from rest_framework import mixins
#Retrieving a list of timesheet entries for a specific user
#Ensure that users can only view and edit their own timesheet entries.
from rest_framework.views import APIView
from rest_framework.response import Response
class TimeSheetCreateView(generics.ListAPIView,mixins.CreateModelMixin):
queryset = TimeSheet.objects.all()
serializer_class = TimeSheetSerializer
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
return TimeSheet.objects.filter(user=user)
else:
return TimeSheet.objects.none()
def post(self, request, *args, **kwargs):
data = request.data
projects= request.data.get("projects")
user = request.user
week_start_date = request.data.get("week_start_date")
hours_worked = request.data.get("hours_worked")
time_sheet = TimeSheet.objects.create(user=user, week_start_date=week_start_date, hours_worked=hours_worked)
# Link TimeSheet with Projects
for project_id in projects:
try:
project = Project.objects.get(pk=project_id)
time_sheet.projects.add(project)
except Project.DoesNotExist:
raise serializers.ValidationError({"projects": f"Project with ID {project_id} not found."})
# Serialize and return created TimeSheet
serializer = TimeSheetSerializer(time_sheet)
return Response(serializer.data)
class TimeSheetListView(generics.ListAPIView):
queryset = TimeSheet.objects.all()
serializer_class = TimeSheetSerializer
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
return TimeSheet.objects.filter(user=user)
else:
return TimeSheet.objects.none()
class TimeSheetDetailView(generics.RetrieveAPIView,mixins.UpdateModelMixin,):
queryset = TimeSheet.objects.all()
serializer_class = TimeSheetSerializer
def get_queryset(self):
user = self.request.user
if user.is_authenticated:
return TimeSheet.objects.filter(user=user)
else:
return TimeSheet.objects.none()
def put(self, request, pk, *args, **kwargs):
try:
time_sheet = TimeSheet.objects.get(pk=pk)
except TimeSheet.DoesNotExist:
return Response({"error": "TimeSheet not found."}, status=status.HTTP_404_NOT_FOUND)
# Update user, week_start_date, and hours_worked if provided
data = request.data
if data.get("user"):
# time_sheet.user = data["user"]
time_sheet.user = request.user
if data.get("week_start_date"):
time_sheet.week_start_date = data["week_start_date"]
if data.get("hours_worked"):
time_sheet.hours_worked = data["hours_worked"]
# Update projects
projects = data.get("projects")
if projects is not None:
# Clear existing projects
time_sheet.projects.clear()
# Link provided projects
for project_id in projects:
try:
project = Project.objects.get(pk=project_id)
time_sheet.projects.add(project)
except Project.DoesNotExist:
return Response({"projects": f"Project with ID {project_id} not found."}, status=status.HTTP_400_BAD_REQUEST)
# Save the updated TimeSheet
time_sheet.save()
serializer = TimeSheetSerializer(time_sheet)
return Response(serializer.data)
4.3: Now create new file name "urls.py"
Put this code on that
from django.urls import path
from . import views
app_name = 'api'
urlpatterns = [
path('timesheets/lists/',views.TimeSheetListView.as_view(),name='timesheet_list'),
path('timesheets/<pk>/update/',views.TimeSheetDetailView.as_view(),name='timesheet_detail'),
path('timesheets/create',views.TimeSheetCreateView.as_view(),name='timesheet_create_entry'),
]
- Best practices for managing nested M2M data in Django
Put Your Thought or Query Here