'InMemoryUploadedFile' object is not callable - django-rest-framework

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)

Related

Getting an AttributeError using RetrieveUpdateDestroyAPIView

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'."

Is there a way to call pagination methods get_next_link and get_previous_link in DRF viewset?

I want to add additional values ​​to the pagination response in my viewset and keep the fields what already there. I was able to add count, but i can`t add next and previous urls to response, is where a way to call pagination_class methods in viewset.
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(queryset, many=True)
return self.get_paginated_response(serializer.data)
else:
status_count = Vps.objects.all().aggregate(
started=Count("status", filter=Q(status="started")),
blocked=Count("status", filter=Q(status="blocked")),
stopped=Count("status", filter=Q(status="stopped"))
)
serializer = self.get_serializer(queryset, many=True)
status_count["results"] = serializer.data
return Response(status_count)
def get_paginated_response(self, data):
status_count = Vps.objects.all().aggregate(
started=Count("status", filter=Q(status="started")),
blocked=Count("status", filter=Q(status="blocked")),
stopped=Count("status", filter=Q(status="stopped"))
)
pagination = self.pagination_class()
page = self.paginate_queryset(data)
return Response(OrderedDict([
('count', pagination.get_count(data)),
('next', self.pagination_class.get_next_link),
('previous', self.pagination_class.get_previous_link),
('started', status_count["started"]),
('blocked', status_count["blocked"]),
('stopped', status_count["stopped"]),
('results', page)
]))
I was able to solve this by creating custom pagination class
class VpsLimitOffsetPagination(LimitOffsetPagination):
def get_paginated_response(self, data):
status_count = Vps.objects.all().aggregate(
started=Count("status", filter=Q(status="started")),
blocked=Count("status", filter=Q(status="blocked")),
stopped=Count("status", filter=Q(status="stopped"))
)
return Response(OrderedDict([
('count', self.count),
('started', status_count["started"]),
('blocked', status_count["blocked"]),
('stopped', status_count["stopped"]),
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))

How can I delete cache_page in Django?

I cached the view using cache_page in Django. But I want to clear the cache_page when a model in my view is updated.
views.py
#method_decorator(cache_page(168 * 3600,), name="dispatch")
class DashboardView(APIView):
permission_classes = [AllowAny]
def get(self, request):
m1 = Model1.objects.all()
m1_serializer = Model1Serializer(sliders, many=True)
m2 = Model2.objects.all()
m2_serializer = Model2Serializer(
collections, many=True
)
m3 = Model3.objects.all()
m3_serializer = Model3Serializer(categories, many=True)
response = {
"m1": m1_serializer.data,
"m2": m2_serializer.data,
"m3": m3_serializer.data,
}
return Response(response)
If a new record is added to any of these models, cache_page should be deleted.
signals.py
#receiver(post_save, sender=Model1)
def clear_cache_when_update_model1(
sender, instance, created, **kwargs
):
if created:
pass
#receiver(post_save, sender=Model2)
def clear_cache_when_update_model2(
sender, instance, created, **kwargs
):
if created:
pass
#receiver(post_save, sender=Model3)
def clear_cache_when_update_model3(
sender, instance, created, **kwargs
):
if created:
pass
I couldn't find the key of cache_page and couldn't find how to clear cache_page.

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)

Updating object using super().update()

I have an object, whose attributes I would like to update. Right now, I am able to update a single attribute eg: name. But the object has several attributes which include name, contact_name, contact_email and contact_phone_number.The following is what I have at the moment.
In views.py
class MerchantViewSet(GetPrefixedIDMixin, viewsets.ModelViewSet):
"""POST support for /merchants/."""
print ("in MerchantViewSet")
queryset = models.Merchant.objects.all()
serializer_class = serializers.CreateMerchantSerializer
lookup_field = "id"
# lookup_value_regex = f"{models.Merchant.id_prefix}_[a-f0-9]{32}"
lookup_value_regex = ".*"
permission_classes = [permissions.MerchantPermission]
def get_queryset(self):
"""Filter the queryset based on the full merchant name or starting with a letter."""
queryset = models.Merchant.objects.all()
search_param = self.request.query_params.get("search", None)
if search_param:
if search_param.startswith("^"):
queryset = queryset.filter(name__istartswith=search_param[1:])
else:
queryset = queryset.filter(name__icontains=search_param)
return queryset
def update(self, request, *args, **kwargs):
request.data["user"] = request.user.id
print (self.get_object().name)
print (request.data)
merchant = self.get_object()
print (response)
print (merchant.name)
for merchants in models.Merchant.objects.all():
print (merchants.id)
if (merchants.id == merchant.id):
merchants.name = request.data["name"]
merchants.save()
I've tried using
response = super(MerchantViewSet, self).update(request, *args, **kwargs)
from what I read in the DRF documentations but using this just returns error 404 when I run my test. Do I simply have to do with I did with name in my code above, with the other attributes? Or is there a more streamlined way to do this?
This is my test:
class MerchantsViewSetTest(tests.BigETestCase): # noqa
#classmethod
def setUpClass(cls): # noqa
super(MerchantsViewSetTest, cls).setUpClass()
cls.application = tests.get_application()
tests.create_group("merchant")
cls.consumer_user = tests.create_consumer()
cls.admin = tests.create_administrator()
cls.merchant_geraldine = models.Merchant.objects.create(
name="Test Account 1",
contact_name="Geraldine Groves",
contact_email="geraldine#example.com",
contact_phone_number="+35310000000",
)
cls. merchant_barbara = models.Merchant.objects.create(
name="Account 2",
contact_name="Barbara",
contact_email="barbara#example.com",
contact_phone_number="+35310000432",
)
def test_edit_merchant(self): # noqa
url = reverse("bige_transactions:merchant-detail", kwargs={'id': self.merchant_geraldine.prefixed_id})
# payload
data = {"name": "Edited"}
# Put data
resp_data = self.put(url, data, user=self.admin, status_code=200)
# Check if data was updated
url = reverse("bige_transactions:merchant-list")
# Try without authenticated user
self.get(url, status_code=401)
# Try with authenticated admin user
resp_data = self.get(url, user=self.admin, status_code=200)
print (resp_data)

Resources