web2py use of modules - python

I have a python function in modules in web2py to send e-mails.It has the following code
message = response.render('scheduler/connectionmessage.html',cont)
I get the error
<type 'exceptions.NameError'> name 'response' is not defined"
How can I make render available in modules? The objective is to have a few such scripts under modules and execute them via scheduler from a stub under controllers.
More code -
def send_email_invites():
from gluon import *
from gluon.template import render
db = current.db
......<execute query and populate dictionary>
message = response.render('scheduler/connectionmessage.html',cont)
That is about it.

Your code already includes from gluon import *, which means you have imported the thread local current object. That object includes the response object for the current request, so you should refer to current.response rather than just response.
Note, this is not necessary in model, controller, and view files because those files are executed in a global environment that already includes the response object (along with much of the rest of the web2py API).
For more details, see http://web2py.com/books/default/chapter/29/04/the-core#Accessing-the-API-from-Python-modules.

Try this before calling response.render()
from gluon.globals import Response
response = Response()
And I know it's tempting, but try to avoid from xyz import * and be explicit.

Related

How to import manager from main without using circular import?

I am trying to import the manager of the login route. It is in python. This is in fastapi. I am using a router so that I can seperate the main file into different pieces. I am trying to make sure that the user is logged in before he/she can see the item page. For this, I need to get the manager from the main file by importing. But, I have already imported the router from the main file, so I cannot import it back, for the system would throw a circular import error.
Here is my code:
In the router's function:
#router.get("/page/items/item/{id}", response_class=HTMLResponse)
def item_page(request: Request, id: int, db: Session = Depends(get_db), user: database_files.models.User = Depends(manager)):
cursor.execute("""SELECT * FROM ratings;""")
reviews = cursor.fetchall()
item = db.query(database_files.models.GamingItem).filter(database_files.models.GamingItem.id == id).first()
return templates.TemplateResponse("item_page_gaming.html", {"request": request, "item": item, "user": user, "reviews": reviews, "title": f"XTreme Gaming - {item.name}"})
I have to import manager, right? There is a main file already importing this so that it can include this router into its own code. So, there would be a circular import. Also, I know what you would put immediately. You would say, "don't import directly like 'from main import manager,' import like 'import main.' Then, you can put 'main.manager' in your dependency. But no, that would not work. This is because the main file is throwing an error when I do that. It says: "Error in loading ASGI app. Could not import module 'main'" I would be very happy if you can provide a solution for this- it would be a huge help to me, for this problem has been stuck with me for a while(some weeks, almost months!)

How to pass an HTTP request as a parameter of a python function?

I'm calling a python function and passing an HTTP request as a parameter but it's not working. I created the function in a View and called it in another, but the parameter fails.
Here's the function I'm calling
def load_colmeias(request):
apiario = request.GET.get('apiario')
if apiario != "":
colmeias = Colmeia.objects.filter(apiario=apiario)
return render(request, 'colmeias_choices.html', {'colmeias': colmeias})
else:
return render(request, 'colmeias_choices.html')
Here I call her
load_colmeias(request)
But the following error occurs
NameError: name 'request' is not defined
I already imported the "urlib" and "requests" libraries but it always gives the same error:
AttributeError: module has no attribute 'GET'
Can someone help me ?? I'm new to Python/Django and I'm still learning how to do things
Check if you have requests installed:
import requests
r=requests.get("https://automatetheboringstuff.com/files/rj.txt")
print(len(r.text))
Now, check:
In load_colmeias(request), make sure the parameter is actually request and not requests throughout.
Your filename is not requests.py; otherwise you would be importing your own file.
request and requests are two different things, one without 's' is a parameter and with 's' is a method. to use requests you have to import requests library this is a third party library to fetch data from an API.
if you want to call this function you have to make a request through an API. create an API for this function and then make a request.
your views.py file:
def load_colmeias(request):
apiario = request.GET.get('apiario')
if apiario != "":
colmeias = Colmeia.objects.filter(apiario=apiario)
return render(request, 'colmeias_choices.html', {'colmeias': colmeias})
else:
return render(request, 'colmeias_choices.html')
Your urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('load_colmeias', views.load_colmeias)
]
Now your API is:
http://127.0.0.1:8000/load_colmeias?apiario=1234
make sure you have used the correct port in the api and have started the server before making the request and pass the correct value of apiario.
There is another way to call this function by using requests library:
import requests
res = requests.get('http://127.0.0.1:8000/load_colmeias?apiario=1234')
print(res.text)
you can use this in any file and call your function like this using this library again the server must be running and pass the correct value of apiario.
Well if you are passing a request parameter then you have to make the request. You can't call it the way you have shown.
I SOLVED THE PROBLEM !! Basically, I just created a function that calls another function and passed the same argument to both... As can be seen below:
def load_colmeias(request):
return carregar_colmeia(request)
I don't know if it's recommended, but it solved my problem of having to rewrite the same code in multiple views.

How to retrieve a listening history object by spotipy?

I'm working at a recommendation system for Spotify and I'm using spotipy on Python. I can't use the function current_user_recently_played, because Python says that the attribute current_user_recently_played isn't valid.
I don't know how to solve this problem, I absolutely need of this information to continue with my work.
This is my code:
import spotipy
import spotipy.util as util
import json
def current_user_recently_played(self, limit=50):
return self._get('me/player/recently-played', limit=limit)
token = util.prompt_for_user_token(
username="212887#studenti.unimore.it",
scope="user-read-recently-played user-read-private user-top-read user-read-currently-playing",
client_id="xxxxxxxxxxxxxxxxxxxxxx",
client_secret="xxxxxxxxxxxxxxxxxxxxxx",
redirect_uri="https://www.google.it/")
spotify = spotipy.Spotify(auth=token)
canzonirecenti= spotify.current_user_recently_played(limit=50)
out_file = open("canzonirecenti.json","w")
out_file.write(json.dumps(canzonirecenti, sort_keys=True, indent=2))
out_file.close()
print json.dumps(canzonirecenti, sort_keys=True, indent=2)
and the response is:
AttributeError: 'Spotify' object has no attribute 'current_user_recently_played'
The Spotify API Endpoints current_user_recently_added exists in the source code on Github, but I don't seem to have it in my local installation. I think the version on the Python package index is out of date, last change to the source code was 8 months ago and last change to the PyPI version was over a year ago.
I've gotten the code example to work by patching the Spotify client object to add the method myself, but this way of doing it is not the best way generally as it adds custom behaviour to a particular instance rather than the general class.
import spotipy
import spotipy.util as util
import json
import types
def current_user_recently_played(self, limit=50):
return self._get('me/player/recently-played', limit=limit)
token = util.prompt_for_user_token(
username="xxxxxxxxxxxxxx",
scope="user-read-recently-played user-read-private user-top-read user-read-currently-playing",
client_id="xxxxxxxxxxxxxxxxxxxxxx",
client_secret="xxxxxxxxxxxxxxxxxxxxxxxx",
redirect_uri="https://www.google.it/")
spotify = spotipy.Spotify(auth=token)
spotify.current_user_recently_played = types.MethodType(current_user_recently_played, spotify)
canzonirecenti = spotify.current_user_recently_played(limit=50)
out_file = open("canzonirecenti.json","w")
out_file.write(json.dumps(canzonirecenti, sort_keys=True, indent=2))
out_file.close()
print(json.dumps(canzonirecenti, sort_keys=True, indent=2))
Other ways of getting it to work in a more correct way are:
installing it from the source on Github, instead of through Pip
poking Plamere to request he update the version on PyPI
subclass the Spotify client class and add the missing methods to the subclass (probably the quickest and simplest)
Here's a partial snippet of the way I've subclassed it in my own project:
class SpotifyConnection(spotipy.Spotify):
"""Modified version of the spotify.Spotipy class
Main changes are:
-implementing additional API endpoints (currently_playing, recently_played)
-updating the main internal call method to update the session and retry once on error,
due to an issue experienced when performing actions which require an extended time
connected.
"""
def __init__(self, client_credentials_manager, auth=None, requests_session=True, proxies=None,
requests_timeout=None):
super().__init__(auth, requests_session, client_credentials_manager, proxies, requests_timeout)
def currently_playing(self):
"""Gets whatever the authenticated user is currently listening to"""
return self._get("me/player/currently-playing")
def recently_played(self, limit=50):
"""Gets the last 50 songs the user has played
This doesn't include whatever the user is currently listening to, and no more than the
last 50 songs are available.
"""
return self._get("me/player/recently-played", limit=limit)
<...more stuff>

Python/Django generate runtime exception

I'm using werkzeug in a Django project using Apache/mod_wsgi. What I want to do is access the werkzeug python shell without there actually being an error. The only way I can figure to do this is to intentionally cause an error when the url pattern url(r'^admin/shell', forceAnError()) is matched.
Admittedly, intentionally causing an error isn't the optimal course of action, so if there's a way to simply call/import/render/access the werkzeug python shell from a template or something, that would be the better solution.
If you wrap your WSGI application in a werkzeug.debug.DebuggedApplication with evalex on, you'll get a shell available at /console:
from werkzeug.wrappers import Request, Response
from werkzeug.debug import DebuggedApplication
#Request.application
def app(request):
return Response("Normal application, nothing to see here...")
app = DebuggedApplication(app, evalex=True)
# console_path is another optional keyword argument.
# you can guess what it does.

Pyramid error: AttributeError: No session factory registered

I'm trying to learn Pyramid and having problems getting the message flash to work. I'm totally new but read the documentation and did the tutorials.
I did the tutorial on creating a wiki(tutorial here, Code here ). It worked great and was pretty easy so I decided to try to apply the flash message I saw in todo list tutorial I did(tutorial here, full code is in a single file at the bottom of the page). Basically when a todo list is created, the page is refreshed with a message saying 'New task was successfully added!'. I wanted to do that everytime someone updated a wiki article in the wiki tutorial.
So I re-read the session section in the documentaion and it says I really just need to do this:
from pyramid.session import UnencryptedCookieSessionFactoryConfig
my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
from pyramid.config import Configurator
config = Configurator(session_factory = my_session_factory)
then in my code I need to add: request.session.flash('New wiki was successfully added!') but I get a error everytime: Pyramid error: AttributeError: No session factory registered
Here's my function(its the exact same from the tutorial except for the request.session.flash part):
#view_config(route_name='edit_page', renderer='templates/edit.pt', permission='edit')
def edit_page(request):
name = request.matchdict['pagename']
page = DBSession.query(Page).filter_by(name=name).one()
if 'form.submitted' in request.params:
page.data = request.params['body']
DBSession.add(page)
request.session.flash('page was successfully edited!')
return HTTPFound(location = request.route_url('view_page',
pagename=name))
return dict(
page=page,
save_url = request.route_url('edit_page', pagename=name),
logged_in=authenticated_userid(request),
)
(note: One thing that I think I could be doing wrong is in the todo example, all the data is in one file, but in the wiki example there are several files..I added my session imports in the view.py file because the flash message is being generated by the view itself).
What am I doing wrong? Any suggestions?
The code you provided is just an example, of course you need to apply it in a correct place. In Pyramid you should (in simple cases ;) have only 1 place in your code where you create just 1 Configurator instance, in the tutorial it is in the main function. A Configurator does not do anything by itself, except create a WSGI application with make_wsgi_app.
Thus, to add sessions there, modify wiki2/src/views/tutorial/__init__.py as follows:
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from pyramid.session import UnencryptedCookieSessionFactoryConfig
from .models import DBSession
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
config = Configurator(settings=settings, session_factory=my_session_factory)
...

Categories