control the empty data in django filter - html

I was coding the backend using Django. I am a beginner in Django. I used a filter to filter some post requests from the HTML form. here is the code.
#api_view(["POST"])
def program_search(request):
Data_List = []
MyFilter = CreateProgram.objects.filter(price__lte=request.POST['price'],
days=request.POST['days']).values()
...
but if I send a request from HTML form that one field of data be null the filter function cant handle it.

I hope you can make use of a simple if... clause to handle the situation
#api_view(["POST"])
def program_search(request):
price = request.POST.get('price')
days = request.POST.get("days")
if price and days:
qs = CreateProgram.objects.filter(price__lte=price, days=days)
else:
# in case of empty filter params from HTML, return empty QuerySet
qs = CreateProgram.objects.none()
# `qs` variable holds your result

Related

how to use two tables inside a query? django

I am trying to use two tables inside one django query. But my query is resulting as "invalid JSON" format.
I want to filter data in Request table by (status="Aprv"). The Request table contains attributes 'from_id' and 'to_id'.
The uid is the id of the user who is currently logged in.
If the current user(uid) is having the 'from_id' of Requests table, the query should return data of 'to_id' from the 'RegUsers' table.
If the current user(uid) is having the 'to_id' of Requests table, the query should return data of 'from_id' from the 'RegUsers' table.
class frnds(APIView):
def post(self, request):
uid = request.data['uid']
ob = Requests.objects.filter(status="Aprv")
fid = ob.value('from_id')
tid = ob.value('to_id')
if fid == uid:
obj = RegUsers.objects.filter(u_id=tid)
else:
obj = RegUsers.objects.filter(u_id=fid)
ser = android_serialiser(obj, many=True)
return Response(ser.data)
I don't want to use foreign keys.
Please Do Help me Correct the syntax.
The error message
You may need to serialize your data to JSON using Django's serializer first:
serializers.serialize('json', obj)
note that you need to import the serializers first from django core
from django.core import serializers
To avoid using JSON serializing in every request I can recommend you to take a look on Parsers on official Django site
https://www.django-rest-framework.org/api-guide/parsers/

Consuming JSON API data with Django

From a Django app, I am able to consume data from a separate Restful API, but what about filtering? Below returns all books and its data. But what if I want to grab only books by an author, date, etc.? I want to pass an author's name parameter, e.g. .../authors-name or /?author=name and return only those in the json response. Is this possible?
views.py
def get_books(request):
response = requests.get('http://localhost:8090/book/list/').json()
return render(request, 'books.html', {'response':response})
So is there a way to filter like a model object?
I can think of three ways of doing this:
Python's filter could be used with a bit of additional code.
QueryableList, which is the closest to an ORM for lists I've seen.
query-filter, which takes a more functional approach.
1. Build-in filter function
You can write a function that returns functions that tell you whether a list element is a match and the pass the generated function into filter.
def filter_pred_factory(**kwargs):
def predicate(item):
for key, value in kwargs.items():
if key not in item or item[key] != value:
return False
return True
return predicate
def get_books(request):
books_data = requests.get('http://localhost:8090/book/list/').json()
pred = filter_pred_factory(**request.GET)
data_filter = filter(pred, books_data)
# data_filter is cast to a list as a precaution
# because it is a filter object,
# which can only be iterated through once before it's exhausted.
filtered_data = list(data_filter)
return render(request, 'books.html', {'books': filtered_data})
2. QueryableList
QueryableList would achieve the same as the above, with some extra features. As well as /books?isbn=1933988673, you could use queries like /books?longDescription__icontains=linux. You can find other functionality here
from QueryableList import QueryableListDicts
def get_books(request):
books_data = requests.get('http://localhost:8090/book/list/').json()
queryable_books = QueryableListDicts(books_data)
filtered_data = queryable_books.filter(**request.GET)
return render(request, 'books.html', {'books':filtered_data})
3. query-filter
query-filter has similar features but doesn't copy the object-orient approach of an ORM.
from query_filter import q_filter, q_items
def get_books(request):
books_data = requests.get('http://localhost:8090/book/list/').json()
data_filter = q_filter(books_data, q_items(**request.GET))
# filtered_data is cast to a list as a precaution
# because q_filter returns a filter object,
# which can only be iterated through once before it's exhausted.
filtered_data = list(data_filter)
return render(request, 'books.html', {'books': filtered_data})
It's worth mentioning that I wrote query-filter.

odoo 10 QWEB report how to pass value that is used in methods in parser?

I have a model that saves reports in binary fields for archiving. To do that I use the pdf_get().
document = self.env['report'].sudo().get_pdf(ids, report_name)
The problem is when I want to create a report that doesn't use the models fields but has to compute values from related models with the model that is pass with ids.
My report model
class ReportHistory(models.AbstractModel):
_name = 'report.hr.report_history'
def _get_report(self, ids[0]):
record = self.env['hr.history'].search([('id', '=', ids[0])])
return record
def _get_company(self, ids):
rec = self._get_report(ids)
if len(rec) > 0:
return rec[0].company_name
My biggest problem is that I can't debug so I can't what data is passed. The print or logger or raise ValidationError won't work. Probably due to running odoo on windows pc.
Every answer that I found it was said to pass values to report like this but it doesn't work.
#api.model
def render_html(self, docids, data=None):
docargs =
'doc_ids': self.ids,
'doc_model': self.model,
'data': data,
'company': self._get_company,
}
return self.env['report'].render()
So how to correctly pass values from methods to report? Or did I only do a dumb mistake?
Try this:
return self.env['report'].render(report_name, docargs)

How to pass RawQuerySet result as a JSONResponse in DJango?

I have two models like this:
class McqQuestion(models.Model):
mcq_question_id = models.IntegerField()
test_id = models.ForeignKey('exam.Test')
mcq_right_answer = models.IntegerField()
class UserMcqAnswer(models.Model):
user = models.ForeignKey('exam.UserInfo')
test_id = models.ForeignKey('exam.Test')
mcq_question_id=models.ForeignKey('exam.McqQuestion')
user_answer = models.IntegerField()
I need to match the user_answer and mcq_right_answer. Able to do that by executing the below raw query.
rightAns=UserMcqAnswer.objects.raw('SELECT B.id, COUNT(A.mcq_question_id) AS RightAns\
FROM exam_mcqquestion AS A\
LEFT JOIN exam_usermcqanswer AS B\
ON A.mcq_question_id=B.mcq_question_id_id\
WHERE B.test_id_id=%s AND B.user_id=%s AND\
A.mcq_right_answer=B.user_answer',[test_id,user_id])
1) But the problem is that couldn't able to pass the result as JSONResponse because it says TypeError: Object of type 'RawQuerySet' is not JSON serializable
2) Is there any alternative to this raw query by using the objects and filtered querysets?
Django's serialize function's second argument can be any iterator that yields Django model instances.
So, in principle, you can use that raw SQL query that you worked on, using something like this:
query = """SELECT B.id, COUNT(A.mcq_question_id) AS RightAns\
FROM exam_mcqquestion AS A\
LEFT JOIN exam_usermcqanswer AS B\
ON A.mcq_question_id=B.mcq_question_id_id\
WHERE B.test_id_id=%s AND B.user_id=%s AND\
A.mcq_right_answer=B.user_answer"""%(test_id, user_id)
and then getting the json data you'll return, as:
from django.core import serializers
data = serializers.serialize('json', UserMcqAnswer.objects.raw(query), fields=('some_field_you_want', 'another_field', 'and_some_other_field'))
Good luck finding the best way to solve your issue
Edit: small fix, added an import
Using raw query is not recommended in Django.
When the model query APIs don’t go far enough, you can fall back to writing raw SQL.
In your case model query API can solve your problem. You can use the following view:
views.py
def get_answers(request):
test = Test.objects.get(name="Test 1")
answers = UserMcqAnswer.objects.filter(test_id=test, user=request.user).annotate(
is_correct=Case(
When(user_answer=F('mcq_question_id__mcq_right_answer'),
then=Value(True)),
default=Value(False),
output_field=BooleanField())
).values()
return JsonResponse(list(answers), safe=False)
Also you can consider Django Rest Framework for serialization of QuerySet.

Use HttpResponse with JSON data in this code

This code seems to work fine when I used Django console and just print it.
reference = FloodHazard.objects.filter(hazard='High')
ids = reference.values_list('id', flat=True)
for myid in ids:
getgeom = FloodHazard.objects.get(id=myid).geom
response = BuildingStructure.objects.filter(geom__intersects=getgeom).values(
'brgy_locat').annotate(counthigh=Count('brgy_locat'))
print response
I was able to show all the values, but when using HttpResponse, it returns an empty set. What is the proper way of returning JSON data from a queryset? So far, tried this:
reference = FloodHazard.objects.filter(hazard='High')
ids = reference.values_list('id', flat=True)
response = {}
for myid in ids:
getgeom = FloodHazard.objects.get(id=myid).geom
response['high'] = BuildingStructure.objects.filter(geom__intersects=getgeom).values(
'brgy_locat').annotate(counthigh=Count('brgy_locat'))
json_post = ujson.dumps(list(response))
return HttpResponse(json_post, content_type='application/json')
There is no much sense in your code. You assign all querysets to the single key in the response dict. You should use a list for this purpose:
As far as I understand the code should be something like this:
response = []
for myid in ids:
getgeom = FloodHazard.objects.get(id=myid).geom
response.extend(BuildingStructure.objects.filter(geom__intersects=getgeom)
.values('brgy_locat')
.annotate(counthigh=Count('brgy_locat')))
json_post = ujson.dumps(response)
If you want to return a hazard level as well as the list of buildings then you can return a dict:
json_post = ujson.dumps({'hazard': 'high', 'buildings': response})