how to capture logged in user's name in django? - python

class logEngine:
def logger(request):
t1 = time.time()
params = {'user': request.user.username,
'ip_address': socket.gethostbyname(socket.gethostname()),
'process_time': time.time() - t1,
}
return params
when I uses request.user.username (which is given in most of the examples in the internet), I get the below error,
AttributeError: 'logEngine' object has no attribute 'user'
Please suggest any other method

I got the solution. It's working fine now
customdblogger_views.py
import socket
import time
import logging
from urllib import request
class logEngine:
def logger(self, request):
t1 = time.time()
params = {'user': request.user.username,
'ip_address': socket.gethostbyname(socket.gethostname()),
'process_time': time.time() - t1,
}
return params
def django_logger(self):
django_logger = logging.getLogger('db')
return django_logger
views.py
# Create your views here.
import logging
import sys
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView
from CustomDBLogger.customdblogger_views import logEngine
from rest_framework import viewsets, status
from rest_framework.decorators import action
db_logger = logging.getLogger('db')
class Request(viewsets.GenericViewSet):
attributes = logEngine()
#action(detail=True)
def test_api_method(self, request):
params2 = {
'class_name': __class__.__name__,
'method_name': sys._getframe().f_code.co_name,
'module_name': __name__,
}
v1 = self.attributes.logger(request)
params2.update(dict(v1))
db_logger.info("Successfully entered into function", extra=params2)
try:
1 / 0
except Exception as e:
db_logger.exception(e, extra=params2)
return Response({'data': True}, status=status.HTTP_200_OK)
finally:
db_logger.info("exited from the function", extra=params2)

Related

How to sort and count values ​when they are selected?

I send a request to the site https://swapi.dev/ the received data needs to be sorted:
Provide the functionality to count the occurrences of values (combination of values) for columns.
For example when selecting the columns ​date​ and ​homeworld​ the table should show the
counts as follows:
my code is not very good because I write something like this for the first time:
import requests
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework import status
from rest_framework.response import Response
from datetime import datetime
from rest_framework import filters
from rest_framework.pagination import PageNumberPagination
from rest_framework.decorators import action
# class StarWarsAPIListPagination(PageNumberPagination):
# page_size = 4
# page_size_query_param = 'page_size'
# max_page_size = 20
class StarView(APIView):
# pagination_class = StarWarsAPIListPagination
# filter_backends = (filters.OrderingFilter)
# ordering_fields = ('name',)
def get(self, request):
date = datetime.today()
page = request.query_params.get('page', 1)
url = f'https://swapi.dev/api/people/?page={page}'
response = requests.get(url, date).json()
return Response(response, status=status.HTTP_200_OK)
class StartDateView(APIView):
def get(self, request):
date = datetime.today()
page = request.query_params.get('page', 1)
url = f'https://swapi.dev/api/people/?page={page}'
response = requests.get(url).json()
a = response['results'][0]['name']
# a = response['results']
# for i in range(len(a)):
# if a[i]["name"] == "R2-D2":
# return Response(a[i]['name'], status=status.HTTP_200_OK)

How is throttling disabled for testing in Django Rest Framework?

Upon implementing a throttle for a REST API, I'm encountering an issue when running my tests all at once.
Upon isolating the subject TestCase and running the test runner, the TestCase passes its assertions. However when all the tests are ran I get the following error: AssertionError: 429 != 400. Which that type of error of course is due to the requests exceeding a rate limit.
How can I disable throttling for the tests so the assertion error is not raised. I decorated the TestCase with #override_settings but that doesn't have any effect.
from copy import deepcopy
from django.conf import settings
from django.test import TestCase, override_settings
from django.contrib.auth.models import User
from rest_framework.test import APITestCase, APIClient
from django.urls import reverse
from ..models import QuestionVote, Question
from users.models import UserAccount
from tags.models import Tag
from .model_test_data import mock_questions_submitted
REST_FRAMEWORK = deepcopy(settings.REST_FRAMEWORK)
del REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']
#override_settings(REST_FRAMEWORK=REST_FRAMEWORK)
class TestUserVoteOnOwnQuestion(APITestCase):
'''Verify that a User cannot vote on their own Question'''
#classmethod
def setUpTestData(cls):
cls.user1 = User.objects.create_user("Me", password="topsecretcode")
cls.user1_account = UserAccount.objects.create(user=cls.user1)
cls.tag = Tag.objects.create(name="Tag")
cls.q = mock_questions_submitted[2]
cls.q.update({'user_account': cls.user1_account})
cls.question = Question(**cls.q)
cls.question.save()
cls.question.tags.add(cls.tag)
def test_vote_on_own_posted_question(self):
self.client.login(username="Me", password="topsecretcode")
response = self.client.put(
reverse("questions_api:vote", kwargs={'id': 1}),
data={"vote": "upvote"}
)
self.assertEqual(response.status_code, 400)
self.assertEquals(
response.data['vote'],
"Cannot vote on your own question"
)
REST_FRAMEWORK = {
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
'DEFAULT_THROTTLE_RATES': {
'voting': '5/minute'
}
}
class UserQuestionVoteView(APIView):
renderer_classes = [JSONRenderer, ]
parser_classes = [JSONParser, ]
permission_classes = [IsAuthenticated, ]
authentication_classes = [SessionAuthentication, ]
throttle_classes = [ScopedRateThrottle, ]
throttle_scope = "voting"
def put(self, request, id):
# import pdb; pdb.set_trace()
account = UserAccount.objects.get(user=request.user)
question = Question.objects.get(id=id)
if account == question.user_account:
return Response(data={
'vote': "Cannot vote on your own question"
}, status=400)
try:
stored_vote = QuestionVote.objects.get(
account=account, question=question
)
serializer = QuestionVoteSerializer(stored_vote, request.data)
except QuestionVote.DoesNotExist:
serializer = QuestionVoteSerializer(data=request.data)
finally:
if serializer.is_valid(raise_exception=True):
question_vote = serializer.save(
account=account,
question=question
)
vote = serializer.validated_data['vote']
if vote == "downvote":
question.vote_tally = F('vote_tally') - 1
else:
question.vote_tally = F('vote_tally') + 1
question.save()
question.refresh_from_db()
return Response(data={
'id': question.id,
'tally': question.vote_tally
})
return Response(serializer.errors)
One way to do this is by setting your config files up to support testing versions:
# config.py
REST_FRAMEWORK = {
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
'DEFAULT_THROTTLE_RATES': {
'voting': '5/minute'
}
}
TESTING = len(sys.argv) > 1 and sys.argv[1] == 'test'
if TESTING:
del REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']
The pro of this approach is you're not hacking away at your application in tests and hiding modifications to the config file - all of your testing based changes are in the same config file as their true values.
The con of this approach is unless your developers know this setting and values are there, they may be scratching their heads as to why the throttling doesn't work in tests, but does at runtime.
My solution was to apply some monkey patching.
I have a throttles.py file where I have custom throttles, such as
class UserBurstRateThrottle(UserRateThrottle):
rate = '120/minute'
What I've done is create a stub allow_request function to always return true, so something like
def apply_monkey_patching_for_test():
def _allow_request(self, request, view):
return True
UserBurstRateThrottle.allow_request = _allow_request
Then, in the test_whatever.py file, I add the following at the top.
from my_proj import throttles
throttles.apply_monkey_patching_for_test()
Another easy way is to disable the cache that's responsible for storing the clients' meta data (https://www.django-rest-framework.org/api-guide/throttling/#setting-up-the-cache). So you need this in your test settings:
CACHES = {
'<throttling-cache-name|default>': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # to prevent API throttling
}
}

How to write Django Unit Test for Authentication Protected REST APIs?

I have looked at two answers on SO that may already have my answer but frankly I just don't understand them. These SO post are: Django Rest Framework API Authentication Test and Django authenticate unit test.
Both of the SO questions use different approaches.
The approach I am attempting to use is this. I have created this class:
from rest_framework.test import APIClient
from django.test import testcases
from django.contrib.auth.models import User
class RemoteAuthenticatedTest(testcases.TestCase):
client_class = APIClient
def setUp(self):
self.username = 'mister_neutron'
self.user = User.objects.create_user(username='mister_neutron',
email='mister_neutron#example.com',
password='F4kePaSs0d')
super(RemoteAuthenticatedTest, self).setUp()
My unit test looks like this:
class InfoViewTestCase(RemoteAuthenticatedTest):
def create_info_record(self):
from random import randint
blade = 'test-blade-host-name-%s' % (randint(0, 100))
breachs = randint(0,100)
dimm = 'test dimm slot %s' % (randint(0,100))
url = reverse('info:info_creat')
data = {
'blade_hostname': blade,
'breach_count': breachs,
'dimm_slot': dimm,
}
response = self.client.post(url,
data,
format='json',
REMOTE_USER=self.username)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Info.objects.count(), 1)
self.assertEqual(Info.objects.get().blade_hostname, blade)
I have this in my settings.py file:
#Authentications
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
When I run my test I get this result:
Failure
Traceback (most recent call last):
File "/myproject/info/tests.py", line 686, in create_info_record
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
AssertionError: 401 != 201
What am I doing wrong?
UPDATE: After following #henriquesalvaro sage advice I have updated my code to this:
from rest_framework.test import APIClient,APITestCase
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
class RemoteAuthenticatedTest(APITestCase):
client_class = APIClient
def setUp(self):
self.username = 'mister_neutron'
self.user = User.objects.create_user(username='mister_neutron',
email='mister_neutron#example.com',
password='F4kePaSs0d')
Token.objects.create(user=self.user)
super(RemoteAuthenticatedTest, self).setUp()
And I updated my test case to this:
class InfoViewTestCase(RemoteAuthenticatedTest):
def create_info_record(self):
from random import randint
blade = 'test-blade-host-name-%s' % (randint(0, 100))
breachs = randint(0,100)
dimm = 'test dimm slot %s' % (randint(0,100))
url = reverse('info:info_creat')
data = {
'blade_hostname': blade,
'breach_count': breachs,
'dimm_slot': dimm,
}
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.user.auth_token.key)
response = self.client.post(url,
data,
format='json',
REMOTE_USER=self.username)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Info.objects.count(), 1)
self.assertEqual(Info.objects.get().blade_hostname, blade)
And now my unit test passes.
After following #henriquesalvaro (see comments) sage advice I have updated my code to this:
from rest_framework.test import APIClient,APITestCase
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
class RemoteAuthenticatedTest(APITestCase):
client_class = APIClient
def setUp(self):
self.username = 'mister_neutron'
self.user = User.objects.create_user(username='mister_neutron',
email='mister_neutron#example.com',
password='F4kePaSs0d')
Token.objects.create(user=self.user)
super(RemoteAuthenticatedTest, self).setUp()
And I updated my test case to this:
class InfoViewTestCase(RemoteAuthenticatedTest):
def create_info_record(self):
from random import randint
blade = 'test-blade-host-name-%s' % (randint(0, 100))
breachs = randint(0,100)
dimm = 'test dimm slot %s' % (randint(0,100))
url = reverse('info:info_creat')
data = {
'blade_hostname': blade,
'breach_count': breachs,
'dimm_slot': dimm,
}
self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.user.auth_token.key)
response = self.client.post(url,
data,
format='json',
REMOTE_USER=self.username)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(Info.objects.count(), 1)
self.assertEqual(Info.objects.get().blade_hostname, blade)
And now my unit test passes.

read body form request in Django

I have a request url http://my_ip:8080 and I have my custom header and body
body as {"test":"hello"} and I can't read body of the POST request. and my views module as,
my views.py
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.db import connection
import json
import re
from hinduja.models import Register
# Register API for Hinduja
#method_decorator(csrf_exempt)
def hinduja_register(req):
agent = is_valid_agent(req)
if agent["result"] == True:
try:
body = get_body(req)
except Exception as e:
print("Exception as " + str(e))
json_data = {"result":"test"}
else:
json_data = error_message('invalid_client')
return response_to_client(json_data)
def is_valid_agent(req):
regex_http_ = re.compile(r'^HTTP_.+$')
regex_content_type = re.compile(r'^CONTENT_TYPE$')
regex_content_length = re.compile(r'^CONTENT_LENGTH$')
request_header = {}
agent = {}
for header in req.META:
if regex_http_.match(header) or regex_content_type.match(header) or regex_content_length.match(header):
request_header[header] = req.META[header]
try:
user_agent = request_header['HTTP_USER_AGENT']
if user_agent == 'XXX':
agent["result"] = True
agent["user_agent"] = user_agent
except Exception as e:
agent["result"] = False
return agent
# Get the request body
def get_body(req):
body_unicode = req.body.decode('utf-8')
body = json.loads(body_unicode)
return body;
# Return error response
def error_message(message):
return {"result":"error", "message": message}
# Return to success response to client
def response_to_client(json_data):
data = json.dumps(json_data)
return HttpResponse(data, content_type='application/json')
while calling
body_unicode = req.body.decode('utf-8')
I got timeout error and got
Broken pipe from ('10.1.1.120', 47496) Can't resolve this error. Can anyone give me suggestion regard this issue
Should it be in this way:
def get_body(req):
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
return body;

Mocking patched class methods is not working

I'm using Django with DRF and python mock. What I am trying to do is to test my views and mock a serializer and some methods.
This is what I have:
views.py
from gmm_mobile.v1.serializers import RegisterParticipationSerializer
from gmm_mobile.v1.exceptions import GameOrCampaignDoesNotExist
from gmm_util.header import Header
from gmm_util.response import ResponseUtils
from gmm_util.permissions import MobileTokenPermission
from gmm_util.permissions import MobileTokenAuthentication
class ParticipantViewMobile(APIView):
permission_classes = (MobileTokenPermission, )
authentication_classes = (MobileTokenAuthentication, )
def post(self, request, service_id, campaign_id):
try:
environment_info = Header.get_environment_info(request)
request.data[Field.GAME_SERVICE_ID] = service_id
request.data[Field.CAMPAIGN] = campaign_id
request.data[Field.LOCATION] = environment_info
participation_serializer = RegisterParticipationSerializer(data=request.data)
participation_serializer.is_valid(raise_exception=True)
participation_serializer.save()
return ResponseUtils.created()
except Http404:
raise GameOrCampaignDoesNotExist()
serializers.py
class RegisterParticipationSerializer(serializers.ModelSerializer):
location = LocationSerializer(many=False)
campaign = serializers.IntegerField()
game_service_id = serializers.CharField(max_length=254)
class Meta:
model = Participation
fields = (Field.PK, Field.EMAIL, Field.GPG_ID, Field.DATE, Field.LOCATION, Field.INFO, Field.CAMPAIGN,
Field.GAME_SERVICE_ID, Field.GCM_ID)
read_only_fields = (Field.GCM_ID,)
test_views.py
from mock import patch
from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework import status
from rest_framework.exceptions import ValidationError
from gmm_mobile.v1.views import ParticipantViewMobile
from gmm_mobile.v1.urls import CONSULT_PARTICIPANT
from gmm_push.environment_configuration import EnvironmentConfiguration
from gmm_util.util_test import JsonObjects
class ParticipantViewMobileTests(APITestCase):
factory = APIRequestFactory()
url = reverse(PARTICIPANT_MOBILE, kwargs={'service_id': 1, 'campaign_id': 1})
def setUp(self):
self.view = ParticipantViewMobile.as_view()
#patch('gmm_mobile.v1.views.RegisterParticipationSerializer')
def test__post__invalid_data__status_400(self, mock_serializer):
# Arrange
mock_serializer.is_valid.side_effect = ValidationError({})
request = self.factory.post(
self.url,
{},
HTTP_X_ENV=JsonObjects.environment_info_1(),
HTTP_X_TOKEN=EnvironmentConfiguration.get_token(False),
format='json')
# Act
response = self.view(request, 1, 1)
# Assert
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
But when I run the test, the side_effect is not working. When I change the .is_valid in the test it has no effect on ParticipantViewMobile.post.
If I do #patch('gmm_mobile.v1.views.RegisterParticipationSerializer.is_valid') and mock_serializer.side_effect = ValidationError({}) it works, but I don't want that because there will be cases that I will need to mock more than one method, like .save and .is_valid.
I also tried to change the import styles views.py and test_views.py but it still didn't work.
Am I doind something wrong or missing anything?
EDIT 1:
I've put prints on the view to try to understand what was happening:
def post(self, request, service_id, campaign_id):
try:
environment_info = Header.get_environment_info(request)
request.data[Field.GAME_SERVICE_ID] = service_id
request.data[Field.CAMPAIGN] = campaign_id
request.data[Field.LOCATION] = environment_info
participation_serializer = RegisterParticipationSerializer(data=request.data)
print RegisterParticipationSerializer.is_valid.side_effect
print participation_serializer.is_valid.side_effect
participation_serializer.is_valid(raise_exception=True)
participation_serializer.save()
return ResponseUtils.created()
except Http404:
raise GameOrCampaignDoesNotExist()
And the output:
{}
None
So, when I create an instance of RegisterParticipationSerializer, I lost the mocked methods. How to avoid this?
Your mock doesn't work because you're mocking the class and not the instance being generated from the class. Try this:
mock_instance = Mock()
mock_instance.is_valid.side_effect = ValidationError({})
mock_serializer.return_value = mock_instance

Categories

Resources