I need read 'dataset' in get function for showing amount and name in the template but I can't access to 'dataset' in get function
class Port(View):
def post(self, request, pid):
session = requests.Session()
response = session.get("http://localhost:8001/pay/" + str(pid))
if response.status_code is 200:
try:
dataset = json.loads(request.body.decode('utf-8'))
print("###",data['amount'],' - ',data['name'],' - ',pid)
return dataset
except ConnectionError as ce:
print(ce)
return HttpResponse("Json Parse Error")
return dataset
else:
return HttpResponse("* wrong request *")
def get(self, request, pid):
context = {
'amount' : dataset['amount'],
'firstname' : dataset['name'],
'order_id' : pid,
}
return render(request, 'index.html',context)
I believe dataset is initialized as an attribute in Port class. Use self.dataset
Related
I have created a fixture to create user and auto login in conftest.py
#pytest.fixture
def test_password():
return 'strong-test-pass'
#pytest.fixture(scope='session')
def create_user(db, test_password):
def make_user(**kwargs):
employee = e_ge_employee.objects.create()
kwargs['password'] = test_password
if 'username' not in kwargs:
kwargs['username'] = str(uuid.uuid4())
if 'employee' not in kwargs:
kwargs['employee'] = employee
return e_ge_user.objects.create(**kwargs)
return make_user
#pytest.fixture
def auto_login_user(db, client, create_user, test_password):
def make_auto_login(user=None):
if user is None:
user = create_user()
client.login(username=user.username, password=test_password)
return client, user
return make_auto_login
and then wrote a testcase to check get api in test_urls.py
class TestUrls:
#pytest.mark.parametrize('param', [
('generate_token'),
('roi_report')
])
def test_generate_token_url(self, auto_login_user, param):
url = reverse(param)
client, user = auto_login_user()
print("client",client)
print("user",user)
resp = client.get(url)
print(resp)
assert resp.status_code == 200
It is giving me the error
{"detail":"Authentication credentials were not provided."}
in my api_views I am using authentication_classes = [SessionAuthentication, ]
permission_classes = [IsAuthenticated, ] these two classes
Can someone please provide me with the solution.....Thanks in Advance
Try rewriting your auto_login_user as follows to force_authenticate the user.
first import APIClient from rest_framework.test
# import
from rest_framework.test import APIClient
#pytest.fixture
def auto_login_user(db, create_user):
api_client = APIClient()
api_client.force_authenticate(user=create_user)
return api_client
and now update your test as follows
def test_generate_token_url(self, auto_login_user, create_user, param):
url = reverse(param)
user = create_user
resp = auto_login_user.get(url)
print(resp)
assert resp.status_code == 200
if this doesn't work maybe the problem is with the create_user fixture
I have created a Custom user Model for my project, using Django 3.2.
To POST/PUT the details in the user I am using restframework.
But while giving the data for "PUT" operation to change some change I am getting the error as JSON parse error - Expecting value: line 1 column 1 (char 0)
def update_masteruser(request,pk):
try:
user = MasterUser.objects.get(pk=pk)
except MasterUser.DoesNotExist:
return JsonResponse({'message': 'The User does not exist'}, status=status.HTTP_404_NOT_FOUND)
if request.method == "PUT":
user_data = JSONParser().parse(request) #problem seems to be on this line
serializer = RegisterUserSerializer(user, data=user_data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
alternate method, this throws 'WSGIRequest' object has no attribute 'data':
def update_masteruser(request,pk):
try:
user = MasterUser.objects.get(pk=pk)
except MasterUser.DoesNotExist:
return JsonResponse({'message': 'The User does not exist'}, status=status.HTTP_404_NOT_FOUND)
if request.method == "PUT":
serializer = MasterUserSerializer(user, data=request.data)
data = {}
if serializer.is_valid():
serializer.save()
data["success"] = "updated"
return Response(data=data)
return Response(serializer.data)
serializers.py
class MasterUserSerializer(serializers.ModelSerializer):
class Meta:
model = MasterUser
fields = "__all__"
I searched the error cause, but couldnt find the reason on it. Why cant it parse the data from request?
Refer to This Documentation given below!!
https://www.django-rest-framework.org/api-guide/parsers/#how-the-parser-is-determined
I tried a alternate method. Instead of using .save , I use .update() and it worked. Something like below
serializer.update(user,serializer.validated_data)
Thanks #bdbd for you response and time! Appreciated
I'm trying to delete an entry in my data base that is returned by a modelviewset get_queryset. When sending a DELETE request through the DRF web interface and via postman, I receive this response "DELETE /api/remove_self/3 HTTP/1.1" 200 along with the data I am trying to delete. The code that gives this result looks like this:
Models.py
class EventAtendee(models.Model):
"""Lists users atending an event"""
#below connects user profile to event
id = models.AutoField(primary_key=True)
event_id = models.IntegerField(null = True)
user_profile = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.event_id
views.py
class RemoveSelfFromEvent(viewsets.ModelViewSet):
"""Remove Yourself From an Event you were attending"""
authentication_classes = (TokenAuthentication,)
serializer_class = serializers.EventAtendeeSerializer
permission_classes = (permissions.UpdateOwnStatus, IsAuthenticated)
def perform_create(self, serializer):
"""Sets the user profile to the logged in user"""
#
serializer.save(user_profile=self.request.user)
def get_queryset(self):
"""
This view should return a list of all the purchases for
the user as determined by the username portion of the URL.
"""
#user_profile = self.kwargs['user_profile']
event_id = self.kwargs['event_id']
return models.EventAtendee.objects.filter(event_id=event_id, user_profile=self.request.user)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
urls.py
router = DefaultRouter(trailing_slash=False)
router.register('events', views.EventAtendeeViewSet, basename='EventAtendee')
urlpatterns = [
path('remove_self/<event_id>', views.RemoveSelfFromEvent.as_view({'get': 'list', 'delete': 'list'})),
]
Any help is much appreciated!
You are mapping the method DELETE to list in your urls.
path('remove_self/<event_id>', views.RemoveSelfFromEvent.as_view({'get': 'list', 'delete': 'list'})),
Correct way to do:
path('remove_self/<pk>', views.RemoveSelfFromEvent.as_view({'get': 'list', 'delete': 'destroy'})),
mapping of various methods:
POST : create
GET : retrieve
PUT : update
PATCH : partial_update
DELETE : destroy
I am a junior developer and trying to write some unittests for our API endpoints. Below is the class that i am testing and the actual test that runs without any issue. (But i am still hesitant that it's hitting my methods). My question is how can i improve my test and also make sure it covers exception(in this case ValueError, SystemError, Exception) by using side_effects(or any better suggestions) from python mock? I read python mock documentation but still can't figure out how to improve and importantly test exceptions.
we use flask microframework, python3.x,
--- Class that i am testing:
#USER_MOD.route('', methods=[HttpMethods.HTTP_POST])
#jwt_required
def create_user():
"""
Private end point for creating users of the system
:return: json
"""
response = ""
try:
logger_obj.info("Request : POST : Create User: {} ".format(request.base_url))
# validating input request
if ValidationUtils.validate_request(request, "CREATE_USER"):
logger_obj.debug("Request Validation Successful")
response = UserService().create_new_user(request)
logger_obj.debug("User Created: {} ".format(response))
return jsonify(response), HTTPStatus.OK
except ValueError as error:
logger_obj.error("ValueError create_user() : {}".format(error))
response = ApplicationUtils.create_api_response(status=ResponseConstants.MSG_ERROR, message=str(error))
return jsonify(response), HTTPStatus.BAD_REQUEST
except SystemError as error:
logger_obj.error("SystemError create_user() : {}".format(error))
response = ApplicationUtils.create_api_response(status=ResponseConstants.MSG_ERROR, message=str(error))
return jsonify(response), HTTPStatus.INTERNAL_SERVER_ERROR
except Exception as error:
logger_obj.error("Exception create_user() : {}".format(error))
response = ApplicationUtils.create_api_response(status=ResponseConstants.MSG_ERROR, message=str(error))
return jsonify(response), HTTPStatus.UNAUTHORIZED
finally:
logger_obj.info("Response : POST : Create User: {} : {}".format(request.base_url, response))
--- Test for above class:
class UserApiTests(DataTestCase): //(or i can use unittest.TestCase)
def setUp(self):
os.environ.update(self.config.to_env())
self.flask_app = make_flask_app()
self.client = self.flask_app.test_client()
self.flask_app.testing = True
#patch('usermgmt.app.services.user_service.UserService.create_new_user')
def test_create_user(self, mock_create_new_user):
# Given
mock_create_new_user.return_value.status_code = 200
mock_create_new_user.return_value = {
"status": "SUCCESS"
}
data_to_post = {
"name": "Test2",
"email": "new-user2#entity.com",
"entity_id": 1,
"is_active": True,
"product_roles": [
{"product_id": 1, "role_id": 4},
{"product_id": 2, "role_id": 4}
],
}
# When
response = self.client.post('/api/usermgmt/users', data=json.dumps(data_to_post), headers={
"Authorization": "Bearer {}".format(get_jwt(identity=self), "Content-Type: application/json")
})
data = response.data
json_data = json.loads(data)
# Then
self.assertEqual(response.status_code, 200)
self.assertEqual(json_data['status'], "SUCCESS")
During my practice I've found that approach quite good.
class TestCreateUser(TestCase):
def test_works_in_correct_case(self):
# equal to your test_create_user
#patch("usermgmt.app.services.user_service.UserService.create_new_user")
def test_handles_value_error_in_create_new_user(self, mock_create_new_user):
mock_create_new_user.side_effect = ValueError
# Your preparation flow here
response = self.client.post('/api/usermgmt/users') # simplified call here is just an example
self.assertEqual(response.status_code, 400)
# check if response body is what you've expected, etc.
I have a post request like
def start_requests(self):
yield FormRequest(url,formdata={'id': "parameter from redis"})
Can I use redis-cli lpush to save post parameter and that my crawler run it?
By default the scrapy-redis queue working only with url as messages.
One message = one url. But you can modify this behavior.
For example you can use some object for your messages/requests:
class ScheduledRequest:
def __init__(self, url, method, body)
self.url = url
self.method = method
self.body = body
Pass it to queue as json encoded dic:
redis.lpush(
queue_key,
json.dumps(
ScheduledRequest(
url='http://google.com',
method='POST',
body='some body data ...'
).__dict__
)
)
And rewrite the make_request_from_data and schedule_next_requests methods:
class MySpiderBase(RedisCrawlSpider, scrapy.Spider):
def __init__(self, *args, **kwargs):
super(MySpiderBase, self).__init__(*args, **kwargs)
def make_request_from_data(self, data):
scheduled = ScheduledRequest(
**json.loads(
bytes_to_str(data, self.redis_encoding)
)
)
# here you can use and FormRequest
return scrapy.Request(url=scheduled.url, method=scheduled.method, body=scheduled.body)
def schedule_next_requests(self):
for request in self.next_requests():
self.crawler.engine.crawl(request, spider=self)
def parse(self, response):
pass