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;
Related
When I test the test_delivery.py with pytest, I get the error: "TypeError: 'Token' object is not callable".
I am using pytest with Django REST. From the examples that I saw, it seems that the code is correct. What am I missing?
basic.py
import pytest
#pytest.fixture
def api_client():
from rest_framework.test import APIClient
return APIClient()
#pytest.fixture
def test_password():
return 'Str0ng-test-pa$$'
import uuid
#pytest.fixture
def create_user(db, django_user_model, test_password):
def make_user(**kwargs):
kwargs['password'] = test_password
if 'username' not in kwargs:
kwargs['username'] = str(uuid.uuid4())
return django_user_model.objects.create_user(**kwargs)
return make_user
from rest_framework.authtoken.models import Token
#pytest.fixture
def get_or_create_token(db, create_user):
user = create_user()
token, _ = Token.objects.get_or_create(user=user)
return token
test_delivery.py
import pytest
from django.urls import reverse
from tests.utils.basic import api_client, get_or_create_token, create_user, test_password
from rest_framework.authtoken.models import Token
#pytest.mark.django_db
def test_unauthorized_request(api_client):
url = reverse('deliveries-list')
response = api_client.get(url)
assert response.status_code == 401
#pytest.mark.django_db
def test_authorized_request(api_client, get_or_create_token):
url = reverse('deliveries-list')
token = get_or_create_token()
api_client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
response = api_client.get(url)
assert response.status_code == 200
[Update] Error details
======================================================= FAILURES =======================================================
_______________________________________________ test_authorized_request ________________________________________________
api_client = <rest_framework.test.APIClient object at 0x7f1ee5e0fa00>
get_or_create_token = <Token: 1771cc20278aed83af8e09646286edd1ef8cb7b7>
#pytest.mark.django_db
def test_authorized_request(api_client, get_or_create_token):
url = reverse('deliveries-list')
> token = get_or_create_token()
E TypeError: 'Token' object is not callable
tests/test_delivery/test_delivery.py:17: TypeError
This is the new test_authorized_request that worked for me. I changed the way that I created the token.
test_delivery.py
#pytest.mark.django_db
def test_authorized_request(api_client, get_or_create_token):
user = User.objects.create_user('test', 'user#example.com', 'Strong-test-pass')
token = Token.objects.create(user=user)
url = reverse('deliveries-list')
api_client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
response = api_client.get(url)
assert response.status_code == 200
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)
I have a ViewSet:
...
from handlers import specific_exception_handler...
...
class SomeViewSet(GenericViewSet):
"""
Some custom generic viewset
"""
queryset = SomeModel.objects.all()
serializer_class = SomeSerializer
parser_classes = (ParserClassThatReadSpecificXML,)
renderer_classes = (RendererClassThatConvertResponseIntoSpecificXML,)
def get_exception_handler(self):
return specific_exception_handler_function_that_return_specific_xml_format_error
#action(methods=['post'], detail=False, url_path='some_url', url_name='some_url')
def register(self, request, format=None):
some_variable = request.data.get('some_value', None)
if not some_variable:
raise ValueError
return Response(data=some_variable, content_type="text/xml; charset=shift_jis")
I have a render:
...
import xmltodict
class RendererClassThatConvertResponseIntoSpecificXML(BaseRenderer):
media_type = 'text/xml'
format = 'txt'
charset = 'shift_jis'
def render(self, data, media_type=None, renderer_context=None):
# return data as non utf-8 xml string
return xmltodict.unparse(data).encode("shift_jis")
I have a custom error handler:
...
from rest_framework.views import exception_handler
def specific_exception_handler_function_that_return_specific_xml_format_error(exc, context):
response = exception_handler(exc, context)
if response is not None:
status_code = response.status_code
else:
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
specific_data_that_will_be_converted_into_xml_by_render = {'ERROR_STATUS': status_code}
headers = {'Retry-After': '300'}
return Response(data, content_type='text/xml; charset=shift_jis', status=status_code, headers=headers)
Problem:
If View's raise ValueError will be raised I get my custom XML formatted error message.
But if some exception will be happened inside render, there is appears Django's standard 500 Server Error message
If I will try to access outside View , there is appears Django's standard 404 Server Error message again
I want to show my custom XML error anytime.
How can I do it?
Okay, here is still no answer, so I will try to answer by myself
how I finally did it:
changed my custom error handlers:
...
from rest_framework.views import exception_handler
from rest_framework import status
from django.http import HttpResponse
...
# ex-specific_exception_handler_function_that_return_specific_xml_format_error
def inside_view_occurred_error_handler(exc, context):
if isinstance(exc, rest_framework.exceptions.NotAuthenticated):
# do custom action for NotAuthenticated
elif isinstance(exc, rest_framework.exceptions.PermissionDenied):
# do custom action for PermissionDenied
elif ...
# do actions for other drf errors if needed
# set status (for example 500)
status = status.HTTP_500_INTERNAL_SERVER_ERROR
# set body
body='<?xml version="1.0" encoding="shift_jis"?><a attr="error">エラー</a>'.encode('shift_jis')
# create response
r = HttpResponse(body, status=status, content_type='text/xml; charset=shift_jis')
# add headers
r['Retry-After'] = '3000'
return r
def outside_view_400_error_handler(request, exception):
# set status
status = status.HTTP_400_BAD_REQUEST
# set body
body='<?xml version="1.0" encoding="shift_jis"?><a attr="error_400">エラー400</a>'.encode('shift_jis')
# create response
r = HttpResponse(body, status=status, content_type='text/xml; charset=shift_jis')
# add headers
r['Retry-After'] = '3000'
return r
def outside_view_500_error_handler(request):
# set status
status = status.HTTP_500_INTERNAL_SERVER_ERROR
# set body
body='<?xml version="1.0" encoding="shift_jis"?><a attr="error_500">エラー500</a>'.encode('shift_jis')
# create response
r = HttpResponse(body, status=status, content_type='text/xml; charset=shift_jis')
# add headers
r['Retry-After'] = '3000'
return r
def outside_view_404_error_handler(request, exception):
# set status
status = status.HTTP_404_NOT_FOUND
# here is no body
# create response
r = HttpResponse(status=status, content_type='text/xml; charset=shift_jis')
return r
added handlers in urls.py
handler400 = 'application.handlers.outside_view_400_error_handler'
handler404 = 'application.handlers.outside_view_404_error_handler'
handler500 = 'application.handlers.outside_view_500_error_handler'
And now if DEBUG = False Django responding anytime with custom responses.
I am sending a get request in my view and then using the response to fill my database and I need some confirmation on the following:
should i make an api call inside of a view?
what should that view response be?
if i have done it wrong then what would be the right way to send get requests in Django?
my_app/views.py
class api(APIView):
template_name = 'payment/api.html'
def get(self, request):
#I SEND THE GET REQUEST HERE
config = configparser.ConfigParser()
config.read('config.ini')
r = requests.get(config['DEFAULT']['api'])
response = r.json()
#HERE I FILTER THE RESPONSE AND PUT IN A DB
for item in response:
if 'Covered Recipient Physician' in item.values():
person, _ = models.Person.objects.get_or_create(
profile_id = int(item['physician_profile_id']),
first_name = item['physician_first_name'].lower(),
last_name = item['physician_last_name'].lower()
)
address, _ = models.Address.objects.get_or_create(
business_street =
item['recipient_primary_business_street_address_line1'].lower(),
city = item['recipient_city'].lower(),
state = item['recipient_state'].lower(),
country = item['recipient_country'].lower()
)
business, _ = models.Business.objects.get_or_create(
business = item['submitting_applicable_manufacturer_or_applicable_gpo_name'].lower(),
)
business_address_link = models.Business_address_link.objects.create(
business = business,
address = address
)
business_address_link.save()
payment = models.Payment.objects.create(
record_id = int(item['record_id']),
amount = float(item['total_amount_of_payment_usdollars']),
date = item['date_of_payment'],
number_of_payments = int(item['number_of_payments_included_in_total_amount']),
payment_form = item['form_of_payment_or_transfer_of_value'],
nature_of_payment = item['nature_of_payment_or_transfer_of_value']
)
payment.save()
person_payment_information = models.Person_payment_information.objects.create(
person = person,
business_address_link = business_address_link,
payment = payment
)
person_payment_information.save()
Try to use this function for GET request -
#require_http_methods(['GET'])
def get_persons(request):
try:
data = list(Message.objects.all.values())
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
Once you get the response and send it to template.html, you can display it in any way you want.
If you want to add information to the DB you better use POST request, for example -
#require_http_methods(['POST'])
def add_person(request):
try:
data = json.loads(request.body)
new_person = Person(**data)
new_person.save()
return render(request=request, template_name='template.html', context={"data": data})
except Exception as e:
return render(request=request, template_name='template.html', context={"error": e})
I am trying to limit the results a user returns during a search based on permissions in django guardian... I have tried many things, but i am going in circles. Any advice would be appreciated :
Scenario : user should only see search results in which they have view_product permissions to.
In my search template i added :
{% load guardian_tags %}
{% get_obj_perms request.user for product as "product_perms" %}
{% if "view_product" in product_perms %}
Which results in Exception Type: VariableDoesNotExist
haystack urls.py
from __future__ import unicode_literals
try:
from django.conf.urls import patterns, url
except ImportError:
from django.conf.urls.defaults import patterns, url
from haystack.views import SearchView
urlpatterns = patterns('haystack.views',
url(r'^$', SearchView(), name='haystack_search'),
)
haystack views.py
from __future__ import unicode_literals
from django.conf import settings
from django.core.paginator import Paginator, InvalidPage
from django.http import Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from haystack.forms import ModelSearchForm, FacetedSearchForm
from haystack.query import EmptySearchQuerySet
RESULTS_PER_PAGE = getattr(settings, 'HAYSTACK_SEARCH_RESULTS_PER_PAGE', 20)
class SearchView(object):
template = 'search/search.html'
extra_context = {}
query = ''
results = EmptySearchQuerySet()
request = None
form = None
results_per_page = RESULTS_PER_PAGE
def __init__(self, template=None, load_all=True, form_class=None, searchqueryset=None, context_class=RequestContext, results_per_page=None):
self.load_all = load_all
self.form_class = form_class
self.context_class = context_class
self.searchqueryset = searchqueryset
if form_class is None:
self.form_class = ModelSearchForm
if not results_per_page is None:
self.results_per_page = results_per_page
if template:
self.template = template
def __call__(self, request):
"""
Generates the actual response to the search.
Relies on internal, overridable methods to construct the response.
"""
self.request = request
self.form = self.build_form()
self.query = self.get_query()
self.results = self.get_results()
return self.create_response()
def build_form(self, form_kwargs=None):
"""
Instantiates the form the class should use to process the search query.
"""
data = None
kwargs = {
'load_all': self.load_all,
}
if form_kwargs:
kwargs.update(form_kwargs)
if len(self.request.GET):
data = self.request.GET
if self.searchqueryset is not None:
kwargs['searchqueryset'] = self.searchqueryset
return self.form_class(data, **kwargs)
def get_query(self):
"""
Returns the query provided by the user.
Returns an empty string if the query is invalid.
"""
if self.form.is_valid():
return self.form.cleaned_data['q']
return ''
def get_results(self):
"""
Fetches the results via the form.
Returns an empty list if there's no query to search with.
"""
return self.form.search()
def build_page(self):
"""
Paginates the results appropriately.
In case someone does not want to use Django's built-in pagination, it
should be a simple matter to override this method to do what they would
like.
"""
try:
page_no = int(self.request.GET.get('page', 1))
except (TypeError, ValueError):
raise Http404("Not a valid number for page.")
if page_no < 1:
raise Http404("Pages should be 1 or greater.")
start_offset = (page_no - 1) * self.results_per_page
self.results[start_offset:start_offset + self.results_per_page]
paginator = Paginator(self.results, self.results_per_page)
try:
page = paginator.page(page_no)
except InvalidPage:
raise Http404("No such page!")
return (paginator, page)
def extra_context(self):
"""
Allows the addition of more context variables as needed.
Must return a dictionary.
"""
return {}
def create_response(self):
"""
Generates the actual HttpResponse to send back to the user.
"""
(paginator, page) = self.build_page()
context = {
'query': self.query,
'form': self.form,
'page': page,
'paginator': paginator,
'suggestion': None,
}
if self.results and hasattr(self.results, 'query') and self.results.query.backend.include_spelling:
context['suggestion'] = self.form.get_suggestion()
context.update(self.extra_context())
return render_to_response(self.template, context, context_instance=self.context_class(self.request))
haystack forms.py
def search(self):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
return self.no_query_found()
sqs = self.searchqueryset.auto_query(self.cleaned_data['q'])
if self.load_all:
sqs = sqs.load_all()
return sqs