NameError: global name is not defined when calling #staticmethod in python - python

I am making a small project and I have a main file, called blog.py and a separate file called users.py in a folder called source.
The layout of the project so far is:
MainFolder
|_blog.py
|
|_source
|_user.py
So, my user.py is very simple and it has a #staticmethod:
from google.appengine.ext import db
class User(db.Model):
username = db.StringProperty(required = True)
pwd_hash = db.StringProperty(required = True)
email = db.StringProperty()
#staticmethod
def searchByUsername(anUserName):
usersList = db.GqlQuery("select * from User where username='" + anUserName + "'")
user = None
for theUser in usersList:
user = theUser
return user
In my blog.py file I try to call that method by making User.searchByUsername(anUserName), however when I do so everythning blows up and I end up with an error (check last 2 lines):
Traceback (most recent call last):
File "/home/pedro/google_appengine/google/appengine/runtime/wsgi.py", line 266, in Handle
result = handler(dict(self._environ), self._StartResponse)
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 1519, in __call__
response = self._internal_error(e)
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 1511, in __call__
rv = self.handle_exception(request, response, e)
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 1505, in __call__
rv = self.router.dispatch(request, response)
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 1253, in default_dispatcher
return route.handler_adapter(request, response)
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 1077, in __call__
return handler.dispatch()
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 547, in dispatch
return self.handle_exception(e, self.app.debug)
File "/home/pedro/google_appengine/lib/webapp2-2.3/webapp2.py", line 545, in dispatch
return method(*args, **kwargs)
File "/home/pedro/google_appengine/hw5/blog.py", line 202, in post
user = User.searchByUsername(username)
NameError: global name 'User' is not defined
I am using from source import user in my blog.py file, and the sources folder also has the __init__.py blank folder, so I know that file is being correctly imported.
Further more, if I just copy/paste the contents of the user.py file into the blog.py file everything works fine (but the I the code gets big and not organized). how can I fix this?

By doing from source import user, you are importing the module user, not the class User inside it. If you want to import that class, you should do from source.user import User. Or you can do from source import user and then refer to the class as user.User.
The staticmethod has nothing to do with it. As the error message suggests, the issue is that it does not know what User is, so it can't even begin to call a method of that class.

Sounds like you may have forgotten to import User into blog.py:
from source.user import User

Related

patching while testing flask app causes AssertionError: View function mapping is overwriting an existing endpoint function

I am trying to write tests for a Flask app.
Currently I have a test that looks like this in a file called test.py.
import mock
from test_helpers import mock_volume_views_setup
class UserTest(unittest.TestCase):
def setUp():
<some set up>
def tearDown():
<some tear down>
#mock.patch('brain_db.views.volume_views_setup')
def test_labeled_scan(self, mock_volume_views_setup):
# test that if path to atlas exists in the container,
self.register_and_commit_user()
self.login_profile_consent()
self.upload('static/test.nii.gz', 1, '04/04/2008', 'GE', '1.5T')
rv = self.app.get('/label_view/1', follow_redirects=True)
response = str(rv.data)
assert "MRI not labeled yet" not in response
test.py lives a top level directory, flask_brain_db.
In flask_brain_db/brain_db/views.py lives the route I'm trying to test. A highly simplified version:
from brain_db_helpers import volume_views_setup
#app.route('/surface_test')
def surface_test():
return render_template('brain_db/surf_view.html')
#app.route('/label_view/<int:scan_number>')
#login_required
def label_view(scan_number):
a, b, c, d = volume_views_setup(scan_number, resource_type='atlas')
if os.path.exists(a):
return render_template('brain_db/scan_view.html')
When I try to run my test, I get
FAIL: test_labeled_scan (test.UserTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1297, in patched
arg = patching.__enter__()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1353, in __enter__
self.target = self.getter()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1523, in <lambda>
getter = lambda: _importer(target)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1210, in _importer
thing = _dot_lookup(thing, comp, import_path)
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1199, in _dot_lookup
__import__(import_path)
File "/usr/src/app/flask_brain_db/brain_db/views.py", line 36, in <module>
#app.route('/surface_test')
File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1250, in decorator
self.add_url_rule(rule, endpoint, f, **options)
File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 66, in wrapper_func
return f(self, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/flask/app.py", line 1221, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: surface_test
I understand what this error is trying to communicate. Somehow my patch decorator is, in an import, re-executing code that defines the routes in views.py, leading to the error. (The error doesn't appear without the patch decorator and mock function). But I don't understand why, or how I am supposed to patch my helper method. I have really struggled with understanding the correct way to refer to the method that needs patching, but looking at this question for example I think I'm doing it right.

Django: model OneToOneField with User can't add default value

I have an model and I want to add an OneToOneField to hold the creator of an object:
models.py
creator = models.OneToOneField(User, blank=True,
default=User.objects.filter(
username="antoni4040"))
I already have a database with items and just want the default value to be the admin user, which has the username "antoni4040". When I try to migrate without the default field it asks for a default value, so I can't get away with it. But here's what I get when running makemigrations:
Migrations for 'jokes_app':
0008_joke_creator.py:
- Add field creator to joke
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 150, in handle
self.write_migration_files(changes)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 178, in write_migration_files
migration_string = writer.as_string()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 167, in as_string
operation_string, operation_imports = OperationWriter(operation).serialize()
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 124, in serialize
_write(arg_name, arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 88, in _write
arg_string, arg_imports = MigrationWriter.serialize(_arg_value)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 433, in serialize
return cls.serialize_deconstructed(path, args, kwargs)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 318, in serialize_deconstructed
arg_string, arg_imports = cls.serialize(arg)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 517, in serialize
item_string, item_imports = cls.serialize(item)
File "/home/antoni4040/Documents/Jokes_Website/django-jokes/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 540, in serialize
"topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: <User: antoni4040>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/1.9/topics/migrations/#migration-serializing
What am I doing wrong?
You are using the queryset User.objects.filter(username="antoni4040"). To get a model instance, you would use User.objects.get(username="antoni4040").
However, you shouldn't use a a model instance for as the default in the model field. There's no error handling if the user does not exist in the database. In fact, if models.py is loaded before you run the initial migrations, then the User table won't even exist so the query will give an error.
The logic to set the default user should go in the view (or Django admin) instead of the models file.
In the admin, you could define a custom form that sets the initial value for the creator field.
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
try:
user = User.objects.get(username="antoni4040")
kwargs['initial']['creator'] = user
except MyModel.DoesNotExist:
pass
super(MyModelForm, self).__init__(*args, **kwargs)
Then use that model form in your admin.
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
...
If you really wanted to do this you can open up a shell and get the id for that User, then set the default to that.
The problem is, why would you do that? The first time you add a model it will use the default correctly. The second time you try to do that, it will fail because it's one to one, not many to one, so it will fail.

"Runtime Error: working outside of application context" when trying to instantiate WTForms object in Flask view

So i have a form defined like this:
class NewDashForm(Form):
tabname = StringField('tabname', validators=[DataRequired(),Length(1,16)])
title = StringField('title', validators=[DataRequired(),Length(1,128)])
And I am importing it in my views.py file, but when I try to instantiate it like this:
form = NewDashForm()
I get the "working outside of application context" error. The application is generated by a "factory" method, like this:
def generate_application(config=None):
application = Flask(__name__)
application.config.from_object(config)
application.register_blueprint(cheda.generate_blueprint(application.config,application.db))
return application
There is some db related stuff that I left out in this last code snippet, but you get the idea. From my understanding, anything that happens from within a view should automatically be under application context, but clearly I am missing something. What am I doing wrong here?
Traceback (most recent call last):
File "/vagrant/venv/cheda_env/bin/cheda-run", line 9, in <module>
load_entry_point('cheda==0.1.0', 'console_scripts', 'cheda-run')()
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/pkg_resources/__init__.py", line 546, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/pkg_resources/__init__.py", line 2666, in load_entry_point
return ep.load()
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/pkg_resources/__init__.py", line 2339, in load
return self.resolve()
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/pkg_resources/__init__.py", line 2345, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "/code/cheda/cheda/cmd/run.py", line 10, in <module>
from .. import application
File "/code/cheda/cheda/application.py", line 16, in <module>
from .blueprints import cheda
File "/code/cheda/cheda/blueprints/cheda.py", line 10, in <module>
from ..views import views as cheda_views
File "/code/cheda/cheda/views/views.py", line 37, in <module>
class NewDash(JsonApiView):
File "/code/cheda/cheda/views/views.py", line 39, in NewDash
form = NewDashForm()
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/wtforms/form.py", line 212, in __call__
return type.__call__(cls, *args, **kwargs)
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/flask_wtf/form.py", line 68, in __init__
csrf_enabled = current_app.config.get('WTF_CSRF_ENABLED', True)
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/werkzeug/local.py", line 338, in __getattr__
return getattr(self._get_current_object(), name)
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/werkzeug/local.py", line 297, in _get_current_object
return self.__local()
File "/vagrant/venv/cheda_env/lib/python3.4/site-packages/flask/globals.py", line 34, in _find_app
raise RuntimeError('working outside of application context')
RuntimeError: working outside of application context
You should only instantiate forms within view fuctions, doing so outside a request doesn't make sense. You are getting the error because it's trying to get data from the request, which isn't present.
If you really need to instantiate it before hand, either pass empty data to it so it doesn't look at the request, or use a request context.
from werkzeug.datastructrues import MultiDict
form = MyForm(MultiDict())
# or
with app.test_request_context():
form = MyForm()
Again, you should never be doing this in your application, a form is only useful inside a view during a request. The test request context would be useful if you wanted to test the form in a unit test.

Python/GAE Attribute Error - webapp2

I am using Nick Johnsons Webapp & Templates application as a base for what I am trying to do. I am getting a "AttributeError: 'NoneType' object has no attribute 'write'" when I try to call the render_template. I know it is because when I instantiate the object "Capture" as X, it doesn't have a response property. I have looked everywhere to find a solution but I cannot find one anywhere.
NOTE: There are other ways to do this, but I need it to work as closely to how I have it setup!
Traceback:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/Users/userx/Documents/_FRESHCUTZ MEDIA/Google/GAE - Test web form 1 /testwebform1/main.py", line 41, in post
x.calculateYear(name, age)
File "/Users/userx/Documents/_FRESHCUTZ MEDIA/Google/GAE - Test web form 1 /testwebform1/main.py", line 49, in calculateYear
self.response.write(self.render_template('index.html', **template_args))
AttributeError: 'NoneType' object has no attribute 'write'
MAIN.PY
import os
import webapp2
from webapp2_extras import jinja2
class BaseHandler(webapp2.RequestHandler):
#webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_template(self, filename, **template_args):
self.response.write(self.jinja2.render_template(filename, **template_args))
class MainPage(BaseHandler):
def get(self):
template_args = {}
self.render_template('index.html', **template_args)
class CaptureDetails(BaseHandler):
def post(self):
name = self.request.get("name").strip()
age = self.request.get("age").strip()
x = Calculate()
x.calculateYear(name, age)
class Calculate(BaseHandler):
def calculateYear(self, name, age):
template_args = {"age": age}
self.render_template('name.html', **template_args)
app = webapp2.WSGIApplication([
('/', MainPage),
('/capture', CaptureDetails),
('/age', Calculate)
], debug=True)
What am I doing wrong? Any help/suggestions are greatly appreciated!
Does it fit your criteria if you make calculateYear a function of your BaseHandler class (or elsewhere if more applicable)? As you guessed, your x isn't being treated as a proper response. When you invoke a webapp2.RequestHandler handler, it calls the method associated with the type of request (so in your case, since you are posting a form, it will call post(), as you know). When you instantiate x and call calculateYear, you aren't specifying a particular method (def get(self), def post(self), etc.), so there is no preparation of a response (when I have a chance I'll dig a little to confirm that this is actually the case - I could be mistaken :) ).
Can't test this right now, but assuming you need to call calculateYear from more than just the CaptureDetails handler, would this work? Here you would be referencing self in the context of your post method, which would invoke the response handling:
class BaseHandler(webapp2.RequestHandler):
#webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_template(self, filename, **template_args):
self.response.write(self.jinja2.render_template(filename, **template_args))
def calculateYear(self, name, age):
template_args = {"age": age}
self.render_template('name.html', **template_args)
Which you could then call from your CaptureDetails handler like:
class CaptureDetails(BaseHandler):
def post(self):
name = self.request.get("name").strip()
age = self.request.get("age").strip()
# Call the function and write the response
self.calculateYear(name, age)
By instantiating Calculate yourself in your CaptureDetails.post method you're not creating it in the same way that WSGIApplication does, so the properties aren't available. Specifically, you're not passing a response to it, so not surprisingly trying to reference it doesn't work.
In this case, I'd copy the contents of calculateYear into your post method - you're not really saving anything by having to create the instance and then call the method on it.
If calculateYear gets more complicated, and you don't want the duplication, then I'd introduce a new method that could be called by both of your hander methods. (It's not really clear from this example though why the Calculate class exists - it doesn't have a 'get' method, so mapping it to /age as you have done isn't going to work.)
Try using self.response.out.write instead of self.response.write.

django exception while using Filter (ImportError: No Module named ..)

When I try using in Django the "filter" Method:
dumpData.objects.filter(bid = True)
I get the following Exception:
ImportError: No module named Trades
File "XXX\CacheUtil.py", line 141, in loadItems print DumpData.objects.filter(bid = True)
File "XXX\site-packages\django\db\models\manager.py", line 141, in filter
return self.get_query_set().filter(*args, **kwargs)
File "X:\Python27\lib\site-packages\django\db\models\query.py", line 550, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "X:\Python27\lib\site-packages\django\db\models\query.py", line 568, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "X:\Python27\lib\site-packages\django\db\models\sql\query.py", line 1194, in add_q
can_reuse=used_aliases, force_having=force_having)
File "X:\Python27\lib\site-packages\django\db\models\sql\query.py", line 1069, in add_filter
negate=negate, process_extras=process_extras)
File "X:\Python27\lib\site-packages\django\db\models\sql\query.py", line 1248, in setup_joins
field, model, direct, m2m = opts.get_field_by_name(name)
File "X:\Python27\lib\site-packages\django\db\models\options.py", line 307, in get_field_by_name
cache = self.init_name_map()
File "X:\Python27\lib\site-packages\django\db\models\options.py", line 337, in init_name_map
for f, model in self.get_all_related_m2m_objects_with_model():
File "X:\Python27\lib\site-packages\django\db\models\options.py", line 414, in get_all_related_m2m_objects_with_model
cache = self._fill_related_many_to_many_cache()
File "X:\Python27\lib\site-packages\django\db\models\options.py", line 428, in _fill_related_many_to_many_cache
for klass in get_models():
File "X:\Python27\lib\site-packages\django\db\models\loading.py", line 167, in get_models
self._populate()
File "X:\Python27\lib\site-packages\django\db\models\loading.py", line 61, in _populate
self.load_app(app_name, True)
File "X:\Python27\lib\site-packages\django\db\models\loading.py", line 76, in load_app
app_module = import_module(app_name)
File "X:\Python27\lib\site-packages\django\utils\importlib.py", line 35, in import_module
__import__(name)
ImportError: No module named Trades
Trade is my Django App wich is in the settings.py under
INSTALLED_APPS = (
(...),
'Trades')
DumpData is defined as:
class DumpData(models.Model):
orderId = models.BigIntegerField()
typeId = models.BigIntegerField()
price = models.DecimalField(decimal_places=2,max_digits=20)
bid = models.BooleanField()
issued = models.DateField()
dateDumped = models.DateTimeField()
If I try only
dumbData.objects.all()
all works fine so it's probably not a Server/DB problem. (Also I can save the Date without an exception).
I didn't found any documentation about it, but I would suggest to use lowercase names for apps.
Also, try :
dumpData.objects.filter(bid = True).all()
Ok i solved my Problem.
The reason because it didnt worked was in the Project Strukture, i had:
\src
\PackageNr1
Main.py <-- File where Django was called.
\PackageNr2 <-- Package for the Django Files
\trades <-- Django App
models.py ,
views ...usw
settings.py <-- Django Settings File
manage.py
Witch this Struckture i could call things like "save()" or "object.all()" and it worked fine. But for most call it didnt worked. So i moved my Django Package into the Main Pakcage and now it works. The new Struckture looks like this:
\src
\PackageNr1
\trades <-- The django app
models.py
views ....
Main.py
settings.py <--Django Files
manage.py
And this works fine for me.

Categories

Resources