Getting an AttributeError using RetrieveUpdateDestroyAPIView - django-rest-framework

I am new to django and am using mongoengine. I am trying to create an employee database using DRF. All of the APIs are working well but whenever I am trying to fetch a single document which has been deleted its giving me an AttributeError at employee/<int:pk>.
This is my models.py file:-
from mongoengine import Document, SequenceField, StringField, IntField, EmailField from enum import Enum from rest_framework.exceptions import ValidationError
class GenderEnums(str, Enum):
MALE = "Male"
FEMALE = "Female"
OTHER = "Other"
#classmethod
def choices(cls):
return [item.value for item in cls]
models.py:-
class Employee(Document):
employee_id = SequenceField(required=False, primary_key=True)
name = StringField(required=True, max_length=50)
age = IntField(required=True, min_value=18, max_value=50)
company = StringField(required=True, max_length=50)
gender = StringField(choices=GenderEnums.choices(), default=GenderEnums.OTHER)
email = EmailField(required=True, unique=True)
password = StringField(required=True)
def clean(self):
if self.gender == GenderEnums.MALE.value and self.age > 30:
raise ValidationError("For male employees, age should be under 31")
elif self.gender == GenderEnums.FEMALE.value and self.age < 20:
raise ValidationError("For female employees, age should be above 20")
serializers.py:-
from rest_framework_mongoengine import serializers
from .models import Employee
class EmployeeSerializer(serializers.DocumentSerializer):
class Meta:
model = Employee
fields = "__all__"
views.py:-
from .serializers import EmployeeSerializer
from .models import Employee
from rest_framework.response import Response
from rest_framework_mongoengine import generics
import logging
from rest_framework.exceptions import ValidationError
from mongoengine import DoesNotExist
import time
logging.basicConfig(filename="logs.txt", filemode="a", level=logging.INFO)
# GeneralSerializer.Meta.model = Employee
# serializer_used = GeneralSerializer
class EmployeeAdd(generics.CreateAPIView):
try:
serializer_class = EmployeeSerializer
logging.info(f"Document created successfully at {time.ctime()}")
except ValidationError as e:
Response(f"Validation error: {e}")
except Exception as e:
logging.error(f"Error occurred: {e}")
Response(f"An error occurred while creating the document")
class EmployeeAll(generics.ListAPIView):
serializer_class = EmployeeSerializer
queryset = Employee.objects.all()
def get_queryset(self):
queryset = self.queryset
params = self.request.query_params
if "name" in params:
queryset = queryset.filter(name=params["name"])
if "age" in params:
queryset = queryset.filter(age=params["age"])
return queryset
class EmployeeOne(generics.RetrieveUpdateDestroyAPIView):
serializer_class = EmployeeSerializer
lookup_field = "pk"
queryset = Employee.objects.all()
def get_object(self):
try:
queryset = self.get_queryset()
obj = queryset.get(pk=self.kwargs[self.lookup_field])
return obj
except Exception as e:
logging.error(
f"Failed to retrieve document with the ID {self.kwargs[self.lookup_field]}"
)
return Response(
{"detail": "An error occurred while processing your request."}, status=500
)
def update(self, request, *args, **kwargs):
try:
response = super().update(request, *args, **kwargs)
logging.info(
f"Successfully updated document with ID {kwargs[self.lookup_field]}"
)
return response
except ValidationError as e:
logging.error(
f"Failed to update document with ID {kwargs[self.lookup_field]} due to validation error: {e}"
)
return Response({"detail": e.detail}, status=e.status_code)
except DoesNotExist:
return Response({"detail": "Document not found."}, status=404)
except Exception as e:
logging.error(
f"Failed to update document with ID {kwargs[self.lookup_field]} due to an error: {e}"
)
return Response(
{"detail": "An error occurred while processing your request."}, status=500
)
def destroy(self, request, *args, **kwargs):
try:
response = super().destroy(request, *args, **kwargs)
logging.info(
f"Successfully deleted document with ID {kwargs[self.lookup_field]}"
)
return Response(
f"Successfully deleted document with ID {kwargs[self.lookup_field]}"
)
except DoesNotExist:
return Response({"detail": "Document not found."}, status=404)
except Exception as e:
logging.error(
f"Failed to delete document with ID {kwargs[self.lookup_field]} due to an error: {e}"
)
return Response(
{"detail": "An error occurred while processing your request."}, status=500
)
from django.urls import path from .views import EmployeeAdd, EmployeeAll, EmployeeOne
urlpatterns = [ path("register", EmployeeAdd.as_view()), path("employees", EmployeeAll.as_view()), path("employee/<int:pk>", EmployeeOne.as_view()), ]
Any help would be very much appreciated. Thank you.
I tried using serializer, serializer_class changed the methods but still getting the AttributeError:
AttributeError: "Got AttributeError when attempting to get a value for field nameon serializerEmployeeSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Response instance. Original exception text was: 'Response' object has no attribute 'name'."

Related

SerializerMethodField doesn't work on DRF

Here is the simplified verison of the Serializer what I have:
class CommentSerializer(serializers.HyperlinkedModelSerializer):
def __init__(self, *args, **kwargs):
init = super().__init__(*args, **kwargs)
return init
username = serializers.ReadOnlyField(source='user.username')
user_id = serializers.ReadOnlyField(source='user.id')
user = UserSerializer(read_only=True)
url_field_name = 'url_api'
# and more definitions
content_type_id = serializers.IntegerField()
site_id = serializers.SerializerMethodField('_siteId')
def _siteId(self, threadedcomment):
site_id = settings.SITE_ID
return site_id
class Meta:
model = ThreadedComment
fields = ('url_api','url','id','title','tree_path','comment','submit_date','submit_date_unix','submit_date_humanized','root_id','is_removed',
'parent_id','last_child_id','newest_activity','depth','username','user_id','object_pk','content_type_id','user',
'site_id',
)
read_only_fields = ('id','title','tree_path','submit_date','root_id','is_removed',
'parent_id','last_child_id','newest_activity','depth','username','user_id',
# 'site_id',
)
class CommentViewSet(viewsets.ModelViewSet):
queryset = ThreadedComment.objects.all().annotate().all()
serializer_class = CommentSerializer
permission_classes = []
filter_backends = [filters.OrderingFilter]
def filter_queryset(self, queryset):
return queryset
def list(self, request):
return super().list(request)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
# site_id = settings.SITE_ID
# serializer.save(user=self.request.user, site_id=site_id, )
return super().perform_create(serializer)
Now I make an http post request on the api as i.e.:
axios.post('/api/comments/', {
"comment":"test.",
"object_pk":34,
"content_type_id":12,
},
It shows me an error:
500 (Internal Server Error)
IntegrityError: NOT NULL constraint failed: django_comments.site_id
The problem (a pure question) is, why the SerializerMethodField doesn't work? I put a breakpoint on the site_id = settings.SITE_ID line, but it doesn't hit, which means the line hasn't even executed.
I also tried putting a set of lines (the commented lines) on perform_create, reading a SO post, but the result is the same, the same error, NOT NULL constraint failed.
I'm certainly passing a value, but it shows it's a null value, saying nothing is passed, what this means? What am I donig wrong here? Thanks.

'InMemoryUploadedFile' object is not callable

While uploading the csv file showing "'InMemoryUploadedFile' object is not callable " this error, i want to import the csv file data into database using APIview.
Here My Apiview
class UploadViewSet(APIView):
parser_classes = (MultiPartParser, FormParser)
permission_classes = (AllowAny,)
serializer_class= UploadSerializer
def post(self, request, *args, **kwargs):
serializer = UploadSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
file = serializer.validated_data['File']
reader = csv.reader(file('file','r'))
for row in reader():
new_company = Company(
name=row['name'],
hr_name=row['hr_name'],
hr_email=row['hr_email'],
hr_verified=row['hr_verified'],
user_id=row['user_id'],
primary_phone=row['primary_phone'],
comments=row['comments'],
)
new_company.save()
return Response({"status": "success"},status.HTTP_201_CREATED)

How do I upload multiple images using django rest framework?

I am learning how to use djangorestframework by building a microblog and I want users to be able to upload multiple (kind of like how twitter works). I got a particular error(check below) after using a particular approach(check code).
I have attached my models.py, serializers.py and views.py file:
MODELS.PY FILE:
class TweetFile(models.Model):
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
file = models.FileField(upload_to='images')
class Tweets(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
texts = models.TextField()
file_content = models.ManyToManyField(TweetFile, related_name='file_content')
date_posted = models.DateTimeField(auto_now_add=True)
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
likes = models.PositiveIntegerField(default=0)
liker = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_like')
# link = models.URLField()
class Meta:
# verbose_name = _('my thing')
verbose_name_plural = _('Tweets')
def __str__(self):
return f"{self.texts}"
SERIALIZERS.PY FILE:
class TweetSerializer(serializers.ModelSerializer):
tweep = serializers.SerializerMethodField('get_tweep_username')
likes = serializers.SerializerMethodField('get_tweet_likes')
liker = serializers.StringRelatedField(many=True)
class Meta:
model = Tweets
fields = ['id','texts', 'file_content', 'date_posted', 'tweep', 'likes', 'liker']
extra_kwargs = {
"file_content": {
"required": False,
}
}
VIEWS.PY FILE:
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def create_tweet(request):
user = request.user
if request.method == 'POST':
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(tweep=user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_405_METHOD_NOT_ALLOWED)
This particular approach gave me this error in my postman:
{
"file_content": [
"Incorrect type. Expected pk value, received InMemoryUploadedFile."
]
}.
Could anybody tell me what I am doing wrong? or what I need to do? any help will be appreciated, thanks.
Okay, so I found a solution to this issue....and this is the code, hopefully someone finds it helpful:
models.py file
class TweetFile(models.Model):
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
media = models.FileField(upload_to='images')
def __str__(self):
return f"{self.tweep.username}'s media images"
class Tweets(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
texts = models.TextField()
file_content = models.ManyToManyField(TweetFile, related_name='file_content', blank=True, null=True)
date_posted = models.DateTimeField(auto_now_add=True)
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = _('Tweets')
def __str__(self):
return f"{self.texts}"
Serializer.py file
from rest_framework import serializers
from tweets.models import Tweets, TweetFile, Comments
class TweetSerializer(serializers.ModelSerializer):
tweep = serializers.SerializerMethodField('get_tweep_username')
class Meta:
model = Tweets
fields = ['id','texts', 'file_content', 'date_posted', 'tweep']
extra_kwargs = {
"file_content": {
"required": False,
}
}
# function that returns the owner of a tweet
def get_tweep_username(self, tweets):
tweep = tweets.tweep.username
return tweep
Views.py file
#api_view(['POST'])
#permission_classes([IsAuthenticated])
#parser_classes([MultiPartParser, FormParser])
def create_tweet(request):
user = request.user
if request.method == 'POST':
files = request.FILES.getlist('file_content')
if files:
request.data.pop('file_content')
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(tweep=user)
tweet_qs = Tweets.objects.get(id=serializer.data['id'])
uploaded_files = []
for file in files:
content = TweetFile.objects.create(tweep=user, media=file)
uploaded_files.append(content)
tweet_qs.file_content.add(*uploaded_files)
context = serializer.data
context["file_content"] = [file.id for file in uploaded_files]
return Response(context, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(tweep=user)
context = serializer.data
return Response(context, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_405_METHOD_NOT_ALLOWED)
configure your urls.py files appropriately and test the endpoint on POSTMAN, everything should work fine.

Assertion through Django restApi

I'm trying to insert records through APIView but it returns error like
Expected a Response, HttpResponse or HttpStreamingResponse to be returned from the view, but received a <class 'NoneType'>
this is views.py
class TrackList(APIView):
def post(self,request, *args, **kwargs):
employee = Employee.objects.filter(username=kwargs.get('username'), password=kwargs.get('password'))
if employee.exists():
serializer_class = TrackSerializer(data = request.data)
try:
if serializer_class.is_valid():
serializer_class.save(employee=employee[0])
return response.Response(serializer_class.data, status = status.HTTP_201_CREATED)
except Exception as e:
print(e)
return response.Response(serializer_class.errors, status = status.HTTP_404_NOT_FOUND)
please help me how could it be fixed?
When employee.exists() == False or serializer_class.is_valid() == False, then the execution moves to the end of the method, where it implicitly returns None.
Fix it with the following. When the employee doens't exist, it will return a Not Found response with a 404 status. When the serializer data is not valid, it will return an empty response with a 400 Bad Request status.
class TrackList(APIView):
def post(self,request, *args, **kwargs):
employee = Employee.objects.filter(username=kwargs.get('username'), password=kwargs.get('password'))
if employee.exists():
serializer_class = TrackSerializer(data = request.data)
try:
if serializer_class.is_valid():
serializer_class.save(employee=employee[0])
return response.Response(serializer_class.data, status = status.HTTP_201_CREATED)
except Exception as e:
print(e)
return response.Response(serializer_class.errors, status = status.HTTP_404_NOT_FOUND)
return response.Response(None, status=status.HTTP_400_BAD_REQUEST)
return response.Response(None, status=status.HTTP_404_NOT_FOUND)

how could I POST the data in DJANGO rest_frame?

I want to insert Track record through a condition but it does not happen. Please help me how could I do fix it?
this is views.py
class Track(APIView):
http_method_names = ['post',]
def post(self,request, *args, **kwargs):
employee = Employee.objects.filter(username=kwargs.get('username'), password=kwargs.get('password'))
if employee.exists():
serializer_class = TrackSerializer
try:
if serializer_class.is_valid():
serializer_class.save()
return Response(serializer_class.data, status = status.HTTP_201_CREATED)
except Exception as e:
print(e)
return Response(serializer_class.errors, status = status.HTTP_404_NOT_FOUND)
urls.py
path('track/<username>/<password>/',views.TrackList.as_view(),name = 'track'),
You have to pass data to your serializer
class Track(APIView):
http_method_names = ['post',]
def post(self,request, *args, **kwargs):
employee = Employee.objects.filter(username=kwargs.get('username'), password=kwargs.get('password'))
if employee.exists():
serializer_class = TrackSerializer(data=request.data)
try:
if serializer_class.is_valid():
serializer_class.save()
return Response(serializer_class.data, status = status.HTTP_201_CREATED)
except Exception as e:
print(e)
return Response(serializer_class.errors, status = status.HTTP_404_NOT_FOUND)

Resources