call the function response in another function in Django RestFramework - django

I tried calling the another function inside the function which will return the response.I have tried this approach but couldn't able to achieve it.
I'm just getting error as
AssertionError at /api/Data/CurrentRunningActivity2/54
Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'NoneType'>`
views.py:
#api_view(['GET'])
def CurrentRunningActivityView2(request, UserID):
if request.method == 'GET':
CurrentRunningActivity(UserID)
def CurrentRunningActivity(UserID):
cursor = connection.cursor()
cursor.execute('EXEC [dbo].[sp_GetCurrentRunningActivity] #UserId=%s',(UserID,))
result_set = cursor.fetchall()
for row in result_set:
TaskId=row[0]
Number=row[1]
Opened=row[2]
Contacttype=row[3]
Category1=row[4]
State=row[5]
Assignmentgroup=row[6]
CountryLocation=row[7]
Openedfor=row[8]
Employeenumber=row[9]
Shortdescription=row[10]
Internaldescription=row[11]
Additionalcomments=row[12]
TaskName = row[1]
print("Number", Number)
return Response({ "TaskId": TaskId, "Number":Number,"Opened":Opened, "Contacttype":Contacttype,
"Category1":Category1, "State":State, "Assignmentgroup":Assignmentgroup, "CountryLocation":CountryLocation,
"Openedfor":Openedfor, "Employeenumber":Employeenumber , "Shortdescription":Shortdescription,
"Internaldescription":Internaldescription, "Additionalcomments":Additionalcomments,"TaskName":TaskName},status=status.HTTP_200_OK)

Put return statement in the CurrentRunningActivityView2 to return the Response from CurrentRunningActivity. Otherwise it won't return the Response from the second function.
#api_view(['GET'])
def CurrentRunningActivityView2(request, UserID):
if request.method == 'GET':
return CurrentRunningActivity(UserID)

Related

Strange TyperError put() missing 1 required positional argument: 'path'

I've been trying to test my PUT method in the following APITestcase:
def test_story_delete(self):
c = APIRequestFactory
user = User.objects.get(username='test1')
payload = {'storyName': 'changetest'}
request = c.put(reverse('storyFunctions',args=[self.room.pk,self.story.pk]), format='json')
force_authenticate(request,user=user)
My URL:
path('room/<int:pk>/story/<int:idStory>/adm', APIHstory.as_view(),name='storyFunctions'),
And I'm keep receiving this error:
TypeError: put() missing 1 required positional argument: 'path'
I don't understand what is going on because i declared the path inside request. Can someone help me?
Edit: sharing the view that I'm testing
class APIstory(APIView):
permission_classes = [IsAuthenticated]
def put(self,request, pk, idStory):
data = self.request.data
pk = self.kwargs['pk']
id = self.kwargs['idStory']
name = data['storyName'].strip()
if name == "" or str.isspace(name) or len(name) < 4:
return Response({"error": "minimum of 4 words"}, status=400)
if PokerRoom.objects.filter(id=pk).exists():
session = PokerRoom.objects.filter(id=pk)
if session[0].status == 'Finished':
return Response({'error': 'Session already ended'}, status=400)
else:
session = PokerRoom(id=pk)
if Story.objects.filter(id=id, idRoom=session).exists():
if not Story.objects.filter(idRoom=session, storyName=name).exists():
for hist in Story.objects.filter(id=id, idRoom=session):
if hist.status == 'Pending':
if hist.storyName == name:
return Response({'error':'story with the same name'}, status=400)
hist.storyName = name
hist.save()
status = hist.status
body = {"id":id,"storyName":name,"status":status}
message_socket("STORY_UPDATE", pk, body)
return Response({'success': 'story {} edited, status is {}.'.format(hist.id,hist.status)})
else:
return Response({'error': 'story already ended'}, status= 400)
else:
return Response({'error': 'story with the same name'}, status= 400)
return Response({'error': 'session doesnt exists.'}, status=400)
else:
return Response({'error': 'session doesnt exists.'}, status=400)
Edit2: I was forgetting to put the body in my request, but now I'm getting the following error: TypeError: super(type, obj): obj must be an instance or subtype of type
Shouldn't you add the request body also in a put request?
Something like this?
request = c.put(reverse('storyFunctions', kwargs={'pk': self.room.pk, 'idStory': self.story.pk}), payload, format='json')
As per the docs

Calling a function name inside a function in Django Rest Framework

I have tried to call the two method inside the function where I couldn't able to call those method. I have tried few approaches but not succeeded. Here, What I have tried
"UserStartShift", "UserStopShift" are the API functions which have GET and POST method in it. These API are working fine individually, I wanted to return a different response using the conditional statement.
views.py:
# startshift
#api_view(['GET'])
def UserStartShift(request):
if request.method == 'POST':
UserId = request.data.get('UserId')
Ip = request.data.get('Ip')
PortNumber = request.data.get('PortNumber')
print("UserId-->", UserId)
print("Ip-->", Ip)
print('Portnumber-->', PortNumber)
cursor = connection.cursor()
cursor.execute('EXEC [dbo].[Usp_StartShift] #UserId=%s, #IP=%s, #Port=%s', (UserId, Ip, PortNumber,))
return Response(True, status=status.HTTP_200_OK)
# endshift
#api_view(['GET'])
def UserStopShift(request, UserId):
try:
users = tblUserShiftDetails.objects.filter(UserId=UserId)
except tblUserShiftDetails.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
cursor = connection.cursor()
cursor.execute('EXEC [dbo].[USP_StopShift] #UserId=%s',(UserId,))
return Response(True)
#UserShiftDetailsView
#api_view(['GET'])
def UserShiftDetailsView(request, userid):
try:
users = tblUserShiftDetails.objects.filter(UserId=userid)
except tblUserShiftDetails.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
if UserStartShift == True:
cursor = connection.cursor()
cursor.execute('EXEC [dbo].[USP_GetCurrentShiftDetails] #UserId=%s',(userid,))
result_set = cursor.fetchall()
for row in result_set:
row = row[0]
return Response({"IsStarted":True,"EstimatedShifEnd":(row + datetime.timedelta(hours=9)).strftime('%d-%m-%Y %H:%M %p'),"ReasonforAccess": "null"})
elif UserStopShift == True :
cursor = connection.cursor()
cursor.execute('EXEC [dbo].[USP_GetCurrentShiftDetails] #UserId=%s',(userid,))
result_set = cursor.fetchall()
for row in result_set:
row = row[0]
return Response({"IsStarted":False,"EstimatedShifEnd":"null","ReasonforAccess": "null"})

Pass a custom param in URL with a ModelViewSet

What's the best way of passing a param using a ModelViewSet? Forexample achieving something like this :
http://127.0.0.1:8000/api/v1/financing-settings/template/?param=block
Below is the approach I was using but found out I have set the param in the body section, but it's not what I want :
class TemplateView(ModelViewSet):
"""ViewSet for Saving Block/ Step template."""
def list(self, request, *args, **kwargs):
"""Get list of Block/Steps with is_process_template is equal to True."""
param = request.data['param']
if param == "block":
_block = Block.objects.filter(is_process_template=True).values()
return JsonResponse({"data": list(_block)}, safe=False, status=200)
elif param == "step":
_step = Step.objects.filter(is_process_template=True).values()
return JsonResponse({"data": list(_step)}, safe=False, status=200)
return Response(status=status.HTTP_204_NO_CONTENT)
param = request.GET.get('param')
or for a post request
param = request.POST.get('param')
param = request.query_params.get('param')

Django get_total_topup() missing 1 required positional argument: 'request'

class IndexAjaxView(View):
def get(self, request):
param = request.GET.get('param')
if param == 'get_total_topup':
return self.get_total_topup()
return JSONResponse({}, status=404)
def get_total_topup(self, request):
return JSONResponse({
'value': 'Rp.{:,.0f},-'.format(
TopUp.objects.filter(owned_by=request.user).aggregate(Sum('amount'))['amount__sum']
)
})
somebody can help me ? I want to get data via ajax, but the response is 500 with message get_total_topup() missing 1 required positional argument: 'request'
Your call in return self.get_total_topup() has no arguments but your definition def get_total_topup(self, request) requires one. Try return self.get_total_topup(request).
class IndexAjaxView(View):
def get(self, request):
param = request.GET.get('param')
if param == 'get_total_topup':
return self.get_total_topup(request) # <--- just change this
return JSONResponse({}, status=404)
def get_total_topup(self, request):
return JSONResponse({
'value': 'Rp.{:,.0f},-'.format(
TopUp.objects.filter(owned_by=request.user).aggregate(Sum('amount'))['amount__sum']
)
})
You are missing one positional argument in the method call.
return self.get_total_topup()
Fix it to
return self.get_total_topup(request)

django reusable redirect best practice

I've got many views that need the same functionality so I'm trying to move that logic into a separate function (not a view function). The function finds a value either in the GET or session and returns a model instance OR redirects to a new page (kind of like forcing a login). The problem is that you can't redirect from a called function (that I know of). How should I handle this scenario?
Here's my code:
# This is the called function
def getActiveShowOrRedirect(request):
show_pk = request.GET.get('s', False)
if not show_pk:
show_pk = request.session.get('show_pk', False)
if not show_pk:
return HttpResponseRedirect('/setup/')
active_show = Show.objects.get(pk=show_pk)
return active_show
def overview(request):
active_show = getActiveShowOrRedirect(request)
scenes = Scene.objects.filter(show=active_show)
scenes = sorted(scenes, key=lambda s: s.name)
if request.method == 'POST':
form = SceneForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
desc = form.cleaned_data['description']
scene = Scene(name=name.lower(), show=active_show, description=desc, creator=request.user)
scene.save()
return HttpResponseRedirect('/overview/')
else:
form = SceneForm(initial={'creator':request.user,'show':active_show})
return render_to_response('vfx_app/overview.html', {'active_show':active_show,'scenes':scenes,'form':form}, context_instance=RequestContext(request))
I suppose I could check the return type in the view function, but that seems kinda messy.
How about a decorator?
def requires_active_show(view):
"The decorated view must take active show as a second argument."
def wrapped(request, *args, **kw):
show_pk = request.GET.get('s') or request.session.get('show_pk')
if not show_pk:
return HttpResponseRedirect('/setup/')
return view(request, Show.objects.get(pk=show_pk), *args, **kw)
return wrapped
#requires_active_show
def overview(request, active_show):
scenes = Scene.objects.filter(show=active_show).order_by('name')
if request.method == 'POST':
form = SceneForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
desc = form.cleaned_data['description']
scene = Scene.objects.create(
name=name.lower(),
show=active_show,
description=desc,
creator=request.user)
return HttpResponseRedirect('/overview/')
else:
form = SceneForm(initial={'creator': request.user, 'show': active_show})
return render('vfx_app/overview.html', {
'active_show': active_show,
'scenes': scenes,
'form': form
})