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
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.
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)
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.
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)
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)