Django views receives the value on noneType from a raw query - django-models

I am adding this new feature of filtering the database displayed, this is the view I wrote
def index(request):
stations=product.objects.distinct("station").all()
if request.method == 'POST':
station=request.POST.get('station')
category=request.POST.get('category')
filterDonations=product.objects.raw('select * from CharApp_products where category="'+category+'"')
# station="'+station+'" and
return render(request,'CharApp/index.html',{'donations':filterDonations,'stations':stations})
else:
donations=product.objects.all()
return render(request,'CharApp/index.html',{'donations':donations,'stations':stations})
and in the Template I have added the feature as shown below:
<select name="Category" id="">
<option selected disabled="True">---Select Category---</option>
<option>food</option>
<option>furniture</option>
<option>books</option>
<option>clothing</option>
<option>others</option>
</select>
<input type="submit" value="Search">
</form>
But it throws the error of receiving a NoneType value and that it cant concatenate it.
TypeError at /home/
can only concatenate str (not "NoneType") to str
Request Method: POST
Request URL: http://localhost:8000/home/
Django Version: 4.0.4
Exception Type: TypeError
Exception Value:
can only concatenate str (not "NoneType") to str
Exception Location: /Users/aayush/VS code projects/Charity project/CharEasy/CharApp/views.py, line 12, in index
Python Executable: /Users/aayush/VS code projects/Charity project/djan/bin/python3
Python Version: 3.9.12
Python Path:
['/Users/aayush/VS code projects/Charity project/CharEasy',
'/opt/homebrew/Cellar/python#3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python39.zip',
'/opt/homebrew/Cellar/python#3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9',
'/opt/homebrew/Cellar/python#3.9/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/lib-dynload',
'/Users/aayush/VS code projects/Charity '
'project/djan/lib/python3.9/site-packages']
Server time: Fri, 20 May 2022 12:26:16 +0000

Related

Direct user upload to GCS with given name and parameters

I want to enable clients of my Python GAE app to upload files directly to GCS using a specific object name and GCS parameters I set up front (such as cache control and ACL), and perform some actions after the upload has finished.
I currently use the blobstore.create_upload_url for this. However, since I cannot give any parameters or object name up front, I need to copy the entire file to a new location on GCS from within the 'uploaded' callback handler. This is time and (compute) resource consuming, and sounds like it could be avoided.
Is there any way to optimize this process?
Can I create an upload URL that will immediately upload an object with the right name and right ACL + Cache control parameters? (I briefly looked at signed URLs, but those don't seem to support a callback handler like the blobstore API does)
If not, is there a way to not have to copy the file byte by byte to the new location and delete it when i'm done? (being able to move a file and change its attributes would be nice)
Update: I just noticed the GCS python client library has copy2 now. I could have sworn this wasn't there before, but it sounds like it answers the second question.
Here is my Python, webapp2, jinja code for a direct upload (post) to GCS using a signed form with a policy document:
def gcs_upload(acl='bucket-owner-read'):
""" jinja2 upload form context """
default_bucket = app_identity.get_default_gcs_bucket_name()
google_access_id = app_identity.get_service_account_name()
succes_redirect = webapp2.uri_for('_gcs_upload_ok', _full=True)
expiration_dt = datetime.now() + timedelta(seconds=300)
policy_string = """
{"expiration": "%s",
"conditions": [
["starts-with", "$key", ""],
{"acl": "%s"},
{"success_action_redirect": "%s"},
{"success_action_status": "201"},
]}""" % (expiration_dt.replace(microsecond=0).isoformat() + 'Z', acl, succes_redirect)
policy = base64.b64encode(policy_string)
_, signature_bytes = app_identity.sign_blob(policy)
signature = base64.b64encode(signature_bytes)
return dict(form_bucket=default_bucket, form_access_id=google_access_id, form_policy=policy, form_signature=signature,
form_succes_redirect=succes_redirect, form_acl=acl)
class GcsUpload(BaseHandler):
def get(self):
self.render_template('gcs_upload.html', **gcs_upload())
And the form fields:
<form method="post" action="https://storage.googleapis.com/{{ form_bucket }}" enctype="multipart/form-data">
<input type="hidden" id="key" name="key" value="images/test.png">
<input type="hidden" name="GoogleAccessId" value="{{ form_access_id }}">
<input type="hidden" name="acl" value="{{ form_acl }}">
<input type="hidden" name="success_action_redirect" value="{{ form_succes_redirect }}">
<input type="hidden" name="success_action_status" value="201">
<input type="hidden" name="policy" value="{{ form_policy }}">
<input type="hidden" name="signature" value="{{ form_signature }}">
<input name="file" type="file">
<input type="submit" value="Upload">
</form>
Docs GCS upload using a form here

How to automatically get email alerts on errors in Google app engine

I maintain a lot of Google App Engine apps and it is very difficult to constantly keep a track of all my servers if they are running smoothly.
It is very embarrassing to wake up only after user complains about a system crash.
Is it possible to constantly get updated about my server health?
Can i get a mail or something in case their is a error on my google app engine application?
Can't wait for Google to take up this requirement
Now it is possible with Stackdriver (acquired by Google and integrated with Google Cloud Platform/App Engine).
Go to https://console.cloud.google.com/errors.
Click Turn on notifications
You can schedule a cron job which can do this for you
First create a entry in cron.yaml
- description: Houston we have a problem Finder
url: /errorfinder/
schedule: every 3 hours
timezone: Asia/Kolkata
Then create an entry in app.yaml
handlers:
- url: /errorfinder/
script: errorfinder.app
secure: always
Now keep errorfinder.py with the following content
import base64
import datetime
import logging
import time
import urllib
import webapp2
from google.appengine.api.logservice import logservice
from google.appengine.api import mail
class MainHandler(webapp2.RequestHandler):
def get(self):
# Set up end time for our query.
end_time = time.time()
start_time = end_time - 10800 # 3 hours before now . same as cronjob interval
html = ''
report_needed = False
# Iterate through all the RequestLog objects, displaying some fields and
# iterate through all AppLogs beloging to each RequestLog count times
for req_log in logservice.fetch(start_time=start_time, end_time=end_time, minimum_log_level=logservice.LOG_LEVEL_WARNING, include_app_logs=True):
report_needed = True
html = html + '<br /> REQUEST LOG <br />'
html = html + 'IP: %s <br /> Method: %s <br /> Resource: %s <br />' % (req_log.ip, req_log.method, req_log.resource)
html = html + 'Date: %s<br />' % datetime.datetime.fromtimestamp(req_log.end_time).strftime('%D %T UTC')
for app_log in req_log.app_logs:
html = html + '<br />  APP LOG<br />'
html = html + '  Date: %s<br />' % datetime.datetime.fromtimestamp(app_log.time).strftime('%D %T UTC')
html = html + '  Message: <b>%s</b><br />' % app_log.message
html = html + '<br /><br /><br /><br />'
if(report_needed):
mail.send_mail(sender="Beagle Bot <bot#urdomain.com>",
to='lazyadmins#urdomain.com',
subject='Houston we have a problem ..',
body=html,
html=html,
reply_to='support#urdomain.com')
self.response.out.write(html)
app = webapp2.WSGIApplication([('/errorfinder/', MainHandler)], debug=True)
You can make the error search close to real time by reducing the cron job interval
There is no automatic way to send alarm mails in case of errors.
You will need to make your own solution: create a cron job that parses logs and sends email about errors. Possibly aggregate similar errors together. Instead of emails you might consider automatically creating an error report in your issue tracking system.
For me, this link did the trick:
https://console.cloud.google.com/user-preferences/communication?project=voilanorbert-1272&utm_source=cloud-notification&utm_medium=email&utm_content=unsubscribe-new-error
To access it, click on the three dot near your avatar on the top right, and select "Preferences".
You can configure your app to send you an email when exceptions are raised. See here for more details: Catch-All global exception handler in App Engine for Python

postLink generates invalid code at CakePHP 2.3

I am using CakePHP 2.3
I have two environments where I have my web application. At the testing environment with the exact same version of the application (all files are the same) I am having a problem with the Form->postLink method.
It shows this error on the Javascript console:
Uncaught TypeError: Object # has no method 'submit' users:119
onclick
Comparing the resulting HTML from both environments I can notice that the attributes name and id generated by this method are repeated more than once in the same page (which shouldn't be like that).
This is the code use to generate those post links:
foreach($users as $user){
$delete = $this->Form->postLink(__('Delete'), array('action' => 'delete', $user['user_id']), __('Are you sure you want to delete %s?', $user['user_id']));
}
This is the problematic generated HTML with repeated values for id and name as you can see:
<!-- link 1 -->
<form action="delete/1/" name="post_51e8019d095f1" id="post_51e8019d095f1" style="display:none;" method="post">
<input type="hidden" name="_method" value="POST"/>
</form>
Delete
<!-- link 2 -->
<form action="delete/2/" name="post_51e8019d095f1" id="post_51e8019d095f1" style="display:none;" method="post">
<input type="hidden" name="_method" value="POST"/>
</form>
Delete
Why is this happening?
Could it be related with the configuration of the web server somehow? I don't see another explanation for it...
Thanks.
The problem was caused by a bug in IIS 7.0.6000.16386 and the PHP function uniqid as pointed out here.
I am using a slightly different version in both environments ( IIS 7.0.6000.16386 vs IIS 7.5.7600.16385) and that was the cause of the problem.
In order to solve it I modified the file lib/Cake/View/Helper/FormHelper.php chaning the line $formName = uniqid('post_'); inside the postLink function to:
$formName = uniqid('post_', true);
That adds more entropy and as the documentation says:
If set to TRUE, uniqid() will add additional entropy (using the combined linear congruential generator) at the end of the return value, which increases the likelihood that the result will be unique.
Update
Ended up having to add one more change due to problems with javascript in forms.
I added one more line after $formName = uniqid('post_', true); so it looks like:
$formName = uniqid('post_', true);
$formName = str_replace('.', '', $formName);

For <input type="file" ...> self.request.POST[name] is just a string

Using the GAE "helloworld" example app as a base, but changing "helloworld.py" to:
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/html'
self.response.write(
"""
<form method="post">
UPLOAD: <input type="file" name="file_param"/>
<br/>
<input type="submit" name="submit_param" value="Submit">
</form>
"""
)
def post(self):
field_storage = self.request.POST["file_param"]
try:
mimetype = field_storage.type
self.response.write("Mimetype: {}".format(mimetype))
except:
self.response.write("No FieldStorage object, field_storage={}".format(field_storage))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Running this in Google Chrome on Mac OSX:
Click "Choose File"
Choose a file to upload
Click "Submit"
The page that comes back says:
No FieldStorage object, field_storage=<the name of the file I uploaded>
According to http://webapp-improved.appspot.com/guide/request.html#files and examples in various posts, self.request.POST[name] should be a cgi.FieldStorage object. But as this example shows, self.request.POST[name] is a string containing the filename of the uploaded file. If it were a cgi.FieldStorage object, I would expect the program to display the mimetype of the uploaded file.
I need the cgi.FieldStorage object so I can get the mimetype and of course the value, that is, the content of the file. What am I doing wrong?
By the way, switching from webapp2 to webapp (using from google.appengine.ext import webapp) made no difference. Also, running it in Safari or Firefox, it behaved the same as in Chrome.
The form's enctype must be multipart/form-data. Please add it as follows (method attribute is case-insensitive):
<form method="POST" enctype="multipart/form-data">
Also, please consider using blobstore upload, because it doesn't have size limit, you can also use Google Cloud Storage as a backend, which will give you more flexibility on ACL and sharing capability.

BadValueError('Property %s must be a float' % self.name) BadValueError: Property USD must be a float

I am having a problem with my Google App Engine Program. I have been staring at it for a few hours now, and don't what the solution is.
I have seen another relevant question "BadValueError: Property category is required" on GAE, but even when I remove the "required=True" condition from both the user and USD variables, I receive the same error.
My program does a simple conversion of USD currency to SR currency.
Unfortunately, I keep getting the error:
BadValueError('Property %s must be a float' % self.name)
BadValueError: Property USD must be a float
code from my main.py
import webapp2
from google.appengine.ext import db
from google.appengine.ext.webapp import template
class Convert(db.Model):
user = db.StringProperty(required=True)
USD = db.FloatProperty(required=True)
SR = db.FloatProperty()
class MainHandler(webapp2.RequestHandler):
def get(self):
conversion=db.GqlQuery('SELECT * FROM Convert')
values={'conversion':conversion}
self.response.out.write(template.render('main.html',values))
def post(self):
prog= Convert(user=(self.request.get('userName')),USD=((float)self.request.get('currency'))),SR=((float)(self.request.get('currency')*3.75)))
prog.put()
self.redirect('/')
app = webapp2.WSGIApplication([('/', MainHandler)], debug=True)
code from my main.html
<tr><td>{% for a in conversion%}
<div align="right" lang="ar"><font size="+1" color="#000000"><strong><font color="#009999">{{a.user}}أدخل:</font>
{{a.USD}}<font color="#990000">م</font> = {{a.SR}}{% endfor %}
</td></tr>
<tr><td>
<form action="" method="post" accept-charset="utf-8">
<p align="right" dir="rtl"><strong><font color="#003366">أدخل الدولار الأمريكي:</font></strong><input type="text" name="currency" value="" id="currency"></input></p>
<p align="right" dir="rtl"><strong><font color="#003366">الرجـاء إدخــال اسمـك:</font></strong><input type="text" name="userName" value="" id="userName"></input></p>
<p align="right"><input type="submit" value="تحويل العملة"></input></p>
</form>
</td></tr>
I'm not able to reproduce your error with the local server, instead I get:
SyntaxError: invalid syntax
Traceback (most recent call last):
...snip...
File "/Users/user/helloworld/main.py", line 16
prog= Convert(user=(self.request.get('userName')),USD=((float)self.request.get('currency'))),SR=((float)(self.request.get('currency')*3.75)))
The suggestion I make in the comments resolves both the syntax issue and your original issue (which I can only get if I remove the (float) statements):
def post(self):
prog= Convert(user=self.request.get('userName'),USD=float(self.request.get('currency')),SR=float(self.request.get('currency'))*3.75)
prog.put()
self.redirect('/')
The really odd part is, I renamed the USD, and SR variables to lowercase, and it worked. I don't know why it insisted the capital USD "Property USD must be a float", but when I changed them to lowercas usd and sr, it ran smoothly.

Resources