Django Azure rest framework call 500 server error - django

I have an django app that is running fine locally, but deployed to azure app service I am getting a 500 error when when it requests data. The app is being deployed in a docker container on an azure app service:
URLs.py
path('primaryexams/', TemplateView.as_view(template_name='xxxDB/primaryexams.html'), name='primaryExams'),
path('primaryexamsdata/', views.PrimaryExamsView.as_view(), name='primaryexam_data'),
views.py
class PrimaryExamsView(generics.ListAPIView):
serializer_class = PrimaryExamSerializer
template_name='xxxDB/primaryexams.html'
def get_queryset(self):
return xxxPrimaryExamData.objects.all()
def filter_for_datatable(self, queryset):
# filtering
search_query = self.request.query_params.get('search[value]')
if search_query:
lookups = Q(xxxid__first_name__icontains=search_query)|Q(xxxid__last_name__icontains=search_query)|Q(xxxid__xx_id__icontains=search_query)
queryset = xxxPrimaryExamData.objects.filter(lookups)
return queryset
def list(self, request, *args, **kwargs):
draw = request.query_params.get('draw')
queryset = self.filter_queryset(self.get_queryset())
recordsTotal = queryset.count()
filtered_queryset = self.filter_for_datatable(queryset)
try:
start = int(request.query_params.get('start'))
except (ValueError, TypeError):
start = 0
try:
length = int(request.query_params.get('length'))
except (ValueError, TypeError):
length = 25
end = length + start
serializer = self.get_serializer(filtered_queryset[start:end], many=True)
response = {
'draw': draw,
'recordsTotal': recordsTotal,
'recordsFiltered': filtered_queryset.count(),
'data': serializer.data,
}
return Response(response)
serializers.py
class PrimaryExamSerializer(serializers.ModelSerializer):
xxx_id = serializers.ReadOnlyField(source='xxxid.xxx_id')
last_name = serializers.ReadOnlyField(source='xxxid.last_name')
first_name = serializers.ReadOnlyField(source='xxxid.first_name')
program_institution = serializers.ReadOnlyField(source='program_institution.institution_id')
program_institution_name = serializers.ReadOnlyField(source='program_institution.institution_name')
test_center_institution = serializers.ReadOnlyField(source='test_center_institution.institution_id', default='none')
class Meta:
model = AbnsPrimaryExamData
fields = (
'id','xxx_id','last_name','first_name','medical_school','program_institution','program_institution_name','graduation_year','test_center_institution'
)
When I try to load the data I get an ajax error, and when I look at the request its getting a 500 server error:
https://xxxinternal.azurewebsites.net/xxxDB/primaryexamsdata/?draw=1&columns%5B0%5D%...blah...blahh
I have other views set up this same way that work just fine, but for what ever reason this view throws this error and displays no data. When I copy the url and paste it into my local version it displays the response just fine.

it turns out my problem was with gunicorn inside the docker. Running the docker locally also failed, but it gave me more information: Bad Request
Request Line is too large (6060 > 4094)
setting --limit-request-line 8000 fixed the issue.

Related

How to pass data saved from a POST method to the GET method using REST API Django (without a model)?

I have created an API that allows me to upload an image using the POST method in POSTMAN. After submission, I want to display that image name after making a GET request. I am not using any model and I don't intend to grab the image from the directory it is stored in; since I will be uploading images in a server later.
I have looked at multiple sources. A few examples are this, and this.
This is my current code so far but not successful:
views.py:
class API(APIView):
parser_classes = (MultiPartParser,)
def get(self, request, *args, **kwargs):
name = self.request.GET.get('image')
if name:
return Response({"img_name": name}, status=200)
return Response({"img_name" : None}, status = 400)
def post(self, request):
file = self.request.data
img_file = file['image'] #store the image data in this variable
if img_file:
uploaded_file = img_file
img = [{"image_name": uploaded_file}]
serializer = ImgSerializer(img, many = True).data
return Response(serializer, status = 200)
else:
return Response("Please upload", status = 400)
serializers.py:
from rest_framework import serializers
class ImgSerializer(serializers.Serializer):
image_name = serializers.CharField()
My expected result within GET request should be like this:
{'image_name' : 'image_name_from_POST_Request'}
But I am getting this result instead:
None
How can I pass data from the POST request to the GET request using Django's rest framework? Is there an efficient way to deploy this requirement without using a model?
I figured it out. I just created a JSON file in the POST method and stored the necessary data in it. Finally, in order to view the data within the GET method, I opened the file and returned it as a Response.
views.py:
class API(APIView):
parser_classes = (MultiPartParser,)
def get(self, request):
with open('data.txt') as json_file:
data = json.load(json_file)
if data:
return Response(data, status=200)
return Response({"name" : None}, status = 400)
def post(self, request):
posted_file = self.request.data
img_file = posted_file['image']
if img_file:
uploaded_file = img_file
data = [{"image_name": uploaded_file}]
json_data = {"image_name": uploaded_file}
data = {}
data['key'] = []
data['key'].append(json_data)
with open('data.txt', 'w') as outfile:
json.dump(image, outfile)
serializer = ImgSerializer(image, many = True).data
return Response(serializer, status = 200)
else:
return Response(serializer.errors, status = 400)

How to make a POST request to the end point, in views in django for chatterbot?

i am new to django!
I want to make a chatterbot chatbot in my website, for which i need to make a POST request in views. I have created a model. I am using mysql database for this.
I have visited github and other website and finally got a code, but it doesn't have the POST request
this is my models.py:
class Response(models.Model):
statement = models.ForeignKey(
'Statement',
related_name='in_response_to',
on_delete=False
)
response = models.ForeignKey(
'Statement',
related_name='+',
on_delete=False
)
unique_together = (('statement', 'response'),)
occurrence = models.PositiveIntegerField(default=0)
def __str__(self):
s = self.statement.text if len(self.statement.text) <= 20 else self.statement.text[:17] + '...'
s += ' => '
s += self.response.text if len(self.response.text) <= 40 else self.response.text[:37] + '...'
return s
this is where i need to make a POST request in views.py
def post(self, request, *args, **kwargs):
response = Response.objects.all()
if request.is_ajax():
input_data = json.loads(request.read().decode('utf-8'))
else:
input_data = json.loads(request.body.decode('utf-8'))
self.validate(input_data)
response_data = self.chatterbot.get_response(input_data)
return JsonResponse(response, response_data, status=200)
def get(self, request, *args, **kwargs):
data = {
'detail': 'You should make a POST request to this endpoint.',
'name': self.chatterbot.name,
'recent_statements': self._serialize_recent_statements()
}
# Return a method not allowed response
return JsonResponse(data, status=405)
If you're using django rest framework (DRF), i recommend you start by doing QuickStart and then Serialization steps. DRF has a really good documentation and in the Serialization you could find how to make a POST request by defining:
Models
Serializers
Api
Routers

Django REST Framework - unittest client failing to resolve hyperlinks relation for POST

I have this test:
class AttributeTest(APITestCase):
def setUp(self):
user1 = User.objects.create(pk=1, username='pepa', email='ads#asasd.cz', is_active=True, is_staff=True)
user1.set_password('mypass')
user1.save()
self.c1 = Campaign.objects.create(pk=1, owner=user1, project_name='c1')
def test(self):
campaign_url = 'http://testserver/api/campaigns/{}/'.format(self.c1.pk)
self.client.login(username='pepa', password='mypass')
data = {
"label": "something_here",
"parent_campaign": campaign_url,
}
# campaign clearly exists (created in setUp) and GET retrieve it:
assert self.client.get(campaign_url).json()['project_name'] == 'c1'
# I can even try it myself using pdb
# but this doesn't work - response return 400 Bad Request
# complaining about the very same hyperlink I can GET above
response = self.client.post('/api/keys', data, format="json")
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
but when run, it fails with {'parent_campaign': ['Invalid hyperlink - No URL match.']}.
When I try using curl or browsable API (outside the test environment), everything works as expected.
My serializer corresponding to the /api/keys:
class AttributeSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name='api:key-detail')
parent_campaign = serializers.HyperlinkedRelatedField(
view_name='api:campaign-detail',
lookup_field='cid',
queryset=Campaign.objects.all())
def _get_user_campaigns(self):
user = self.context['view'].request.user
return Campaign.objects.filter(owner=user)
def get_fields(self, *args, **kwargs):
fields = super(AttributeSerializer, self).get_fields(*args, **kwargs)
fields['parent_campaign'].queryset = self._get_user_campaigns()
return fields
class Meta:
model = Key
fields = ("id", 'url', "label", 'parent_campaign')
Using serializer directly:
(Pdb) from api.attribute.serializers import AttributeSerializer
(Pdb) ser = AttributeSerializer(data=data)
(Pdb) ser.is_valid()
True
(Pdb) ser.save()
<Key: Something1 | MAROO | CID: lrvyw93>
Try reversing your url name and passing c1.pk as a url parameter, not just formatting it into your url:
from rest_framework.reverse import reverse
campaign_url_name = 'api:campaign-detail' # Use URL name instead of raw URL path
response = self.client.get(reverse(campaign_url_name, kwargs={'pk': self.c1.pk}))
I don't know why, but the results of tests had to be somehow cached. I restarted the PC and it worked with exactly the same commit. Solved.

Cache staleness, even though I am not using a cache

I have uploaded my Django site on a development server at Digital Ocean and started serving it using apache2 and mod_wsgi. I am also using apache2 to serve static content. It's a fresh installation of Debian on the server, and have done minimal changes.
I am using Django Haystack and Solr to support full-text search. I've checked that both the database and Solr are kept up to date.
Now, if the url I use to retrieve a page contains a query string (it can be as small a ?asd, where asd is not a valid param) everything comes out fine.
If however it does not contain such a query string, I get a version of the page that can be several hours (days?) old, even containing items I've deleted from the database.
The issue is resolved as soon as I restart apache2.
Doing apache2ctl -M | grep cache returns nothing, and settings.py does not reference caching either. Anyone have an idea what could be the cause of this?
Update: my view is a standard search view:
class SearchView(SearchView):
form_class = ArticleSearchForm
template_name = 'articles/index.html'
paginate_by = 5
def get_queryset(self):
queryset = super(SearchView, self).get_queryset()
return queryset
def get_context_data(self, *args, **kwargs):
context = super(SearchView, self).get_context_data(*args, **kwargs)
context['ctx'] = context
context['articles'] = map(lambda o: o.object, context['object_list'])
return context
And the associated search form:
class ArticleSearchForm(SearchForm):
start_date = forms.DateField(required=False, widget=forms.DateInput(attrs={ 'id': 'start_date', 'class': 'form-control' }))
end_date = forms.DateField(required=False, widget=forms.DateInput(attrs={ 'id': 'end_date', 'class': 'form-control'}))
def __init__(self, *args, **kwargs):
super(ArticleSearchForm, self).__init__(*args, **kwargs)
self.fields['q'].widget.attrs['class'] = 'form-control'
def search(self):
sqs = super(ArticleSearchForm, self).search()
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get('q'):
sqs = self.searchqueryset.all()
if self.cleaned_data['start_date']:
sqs = sqs.filter(pub_date__gte=self.cleaned_data['start_date'])
if self.cleaned_data['end_date']:
sqs = sqs.filter(pub_date__lte=self.cleaned_data['end_date']+datetime.timedelta(days=1))
return sqs
But considering the page I get is inconsistent with what's in the database, I don't think my code gets called at all.
Update 2: It's weirder than this. Sometimes upon hitting refresh on my browser I get correct results. Hitting refresh again a couple of times I get incorrect results again. I tried wgetting the page on the server (via localhost) and I get incorrect results.

Starting a new thread using django and apache

I am writing a web application using django and part of it requires me to download images given by google image search and store it in a directory onto the server. Here is the code I have written:
def post(self, request, *args, **kwargs):
image = request.FILES['image_file']
query = json.loads(request.POST['metadata'])
owner = User.objects.filter(username="jane")[0]
imageSearch = utils.GoogleImageSearch(query=query['query'], user=owner)
instance = ModelInstance(user=owner, raw_image=image, metadata=str(query))
instance.save()
someThread = utils.SomeThread(InstanceModel=instance, googleImageSearch=imageSearch)
someThread.start() #This line does not start a new thread on apache
someThread.join()
return Response(status=status.HTTP_200_OK)
Here is my utils.py
class GoogleImageSearch(object):
query = ""
directoryToSave = ""
numberOfImages = ""
user = ""
def initializeDirectoryStructure(self):
pathToStoreImages = self.directoryToSave
if os.path.exists(pathToStoreImages):
shutil.rmtree(pathToStoreImages)
os.makedirs(pathToStoreImages)
def __init__(self, query, user):
self.query = query
self.numberOfImages = constants.NUMBER_OF_SEARCH_RESULTS
self.user = user
self.directoryToSave = os.path.join(constants.IMAGE_CONTAINER_ROOT, user.username)
self.initializeDirectoryStructure()
def ImageSearch(self):
exitCode, numberOfImages = imagesearch.searchAndSave(self.query, os.path.join(constants.IMAGE_CONTAINER_ROOT, self.user.username) , constant$
class SomeThread(Thread):
def init(self, mosaicModel, googleImageSearch):
Thread.init(self)
self.mosaicModel = mosaicModel
self.googleImageSearch = googleImageSearch
def run(self):
self.googleImageSearch.ImageSearch()
When I run this code with the django development server, it runs fine.
But when I run this on Apache, the thread never starts.
I am guessing that apache does not allow new threads to be created from the django application.
I wanted to know if there any way(may be some apache configuration file changes) to start the thread.
Thanks in advance.