How to $http post to the datastore - python

I am building a simple site using python, jinja2 and specifically on one page I'm using angularjs. I'm relatively new to jinja2 and angular. I need help posting to the GAE datastore and displaying the comment dynamically without reloading the page (angular). Here's handler part in the main.py:
class expHandler(webapp2.RequestHandler):
def get(self):
title="Colin_MK: Experience"
recommendations = Recommendation.query()
self.response.out.write(json.dumps([rec.to_dict() for rec in recommendations]))
template_vars = {'title': title, 'recommendations': recommendations}
template = JINJA_ENVIRONMENT.get_template('/exp.html')
self.response.out.write(template.render(template_vars))
def post(self):
r = json.loads(self.request.body)
new_comment = Recommendation(comment=r['comment'])
new_comment.put()

Related

Redirection in django and passing arguments

I spent some time reading through the documentation and forums, but not sure I understand this. I have this bit of code in the views of my app:
def billboard_index(request):
if request.method == 'POST':
form = SpotiForm(request.POST)
if form.is_valid():
date = form.cleaned_data['spotiread_date']
try:
url = 'https://www.billboard.com/charts/hot-100/' + date
billboard = requests.get(url)
billboard.raise_for_status()
except:
print("No response")
else:
soup = BeautifulSoup(billboard.text, 'html.parser')
positions = [int(i.text) for i in soup.find_all(name='span', class_='chart-element__rank__number')]
songs = [i.text for i in soup.find_all(name='span', class_='chart-element__information__song')]
artists = [i.text for i in soup.find_all(name='span', class_='chart-element__information__artist')]
top100 = list(zip(positions, songs, artists))
if Top100model.objects.exists():
Top100model.objects.all().delete()
for position in top100:
top100data = Top100model(
idtop=str(position[0]), artist=str(position[2]), song=str(position[1])
)
top100data.save()
params = {
'client_id': SPOTIPY_CLIENT_ID,
'response_type': 'code',
'redirect_uri': request.build_absolute_uri(reverse('spotiauth')),
'scope': 'playlist-modify-private'
}
query_string = urlencode(params)
url = '{}?{}'.format('https://accounts.spotify.com/authorize', query_string)
return redirect(to=url)
# if a GET (or any other method) we'll create a blank form
else:
form = SpotiForm()
return render(request, 'billboardapp.html', {'form': form})
on billboard_index I have a form with one field in which user puts a date. This date is then used as an input for a webscraper. I save the scraped data in the database, this works (I know this code will break in couple instances, but I'll deal with this later). Next I want to follow the spotify authorization flow, so I redirect to a url at spotify/authorization, it works. This gives me the code back when I'm redirected to spotiauth.html. At the same time, I print there all the database entries that were added during scraping. This is the spotiauth view:
def spotiauth(request):
Positions100 = Top100model.objects.all()
print(request)
context = {
'positions': Positions100,
}
return render(request, 'spotiauth.html', context=context)
I have couple questions:
How do I pass additional arguments to the spotiauth view? I tried
return redirect(to=url, date=date)
But I can't access it in spotiauth view. So I don't really want to pass it in the url, I just want it as an argument to another function, is this doable?
Is this the actual way to go about it? Not sure this is the simplest thing to do.
Thank you for your help!
Authentication is something that should be handled in a generic way, and not individually and explicitly per request. This is because you don't want to duplicate the authentication code in every request that needs authentication.
Lucky you, you are using Django which already comes with an authentication and authorization layer, and a great community that creates great libraries such as django-allauth that integrate OAuth2 authentication into Django's authentication layer.
OAuth2 against Spotify is what you are trying to implement here. Just
include django-allauth via pip,
configure the Spotify provider in the settings following their documentation,
include their URLs for login and registration (see their docs)
... and you should be able to sign into your app using a Spotify account.
For your regular views then, the decorator login_required would then suffice.
Django-allauth will do the following:
for users who sign in via OAuth2 providers, regular Django accounts will be created automatically
you can see these users in the Django admin, in the same list as the regular Django users
you can manage the configuration of the OAuth2 provider configuration via the Django Admin - django-allauth brings a model with an admin for it
django-allauth brings additional functionality like email verification, multiple email address management etc.
If you want to style the login and registration pages, you can implement your own templates using django-allauth's templates as basis.

How to implement pagination in a Django and React app without using the REST framework?

I am working on a website whose back-end is in Django and front-end is developed using React. I want to add the pagination feature in the website but don't know how it will be implemented in the frontend part.
I want to send the total page count to the react app.
I have written the following code in my views function till now
def index(request):
influencers = Influencer.objects.all()
paginator = Paginator(influencers,16)
page = request.GET.get('page')
paged_listings = paginator.get_page(page)
user_list = UserList.objects.all().filter(user_id = request.user.id)
queryset = list(chain(paged_listings,user_list),paginator.count)
ser_query = serializers.serialize('json', queryset)
return HttpResponse(ser_query)
Also I am not using REST framework to develop the back-end site.
I want to know what information I have to send to the React front-end site for this to work. How should I proceed?
I'd recommend you do use django-rest-framework because it's probably easier with pagination.
However, if you want to avoid that you could pass your own structure (obviously, you may need to pass other information such as next page/previous page etc).
The challenge here is ensuring everything is JSON serializable - that means for Queryset you have to use .values() and wrap the result with list(). For Paginator you need to wrap with list().
from django.http.response import JsonResponse
def index(request):
influencers = Influencer.objects.all().values()
paginator = Paginator(influencers,16)
page = request.GET.get('page')
paged_listings = paginator.get_page(page)
user_list = UserList.objects.all().filter(user_id = request.user.id).values()
queryset = list(chain(paged_listings,user_list),paginator.count)
content = {'total_page_count': paginator.num_pages, 'data': queryset}
return JsonResponse(content)

Heroku mLab MongoDB admin user not authorized for query in Flask application

I have this section of code, which is part of my Flask application. I am using flask_mongoengine.
app = Flask(__name__)
app.config.from_object('config')
db = MongoEngine(app)
from .models import *
#app.context_processor
def inject_config():
return dict(Config.objects.first(), version=version)
Config is a class within .models that extends Document.
class Config(Document):
title = StringField()
description = StringField()
keywords = StringField()
author = StringField()
version = StringField()
meta = {"collection": "web_config"}
Upon calling Config.objects, it's returning an error:
pymongo.errors.OperationFailure: database error: not authorized for query on heroku_dptwtq1j.web_config
I'm logged in through the admin user. Why am I not authorized for query? Also, how do I authorize myself to query?
I have no trouble querying through another application that uses PyMongo, so why is it not working in Flask?
If you still want to use flask_mongoengine there is a work around mentioned in https://github.com/MongoEngine/mongoengine/issues/851 which fixed it for me (though not ideal)
From allanlei:
My work around is actually to patch flask-mongoengine.connection._resolve_settings() to pass the host=mongodb://.... to mongoengine.connect()
Thanks to Chuck from mLabs who helped me find it.
So, answering my own question: the issue was probably in the flask_mongoengine library. I switched to just mongoengine and it worked fine.

Google App Engine: Creating an Ecommerce website

I'm working on an ecommerce website, using Google App Engine with Python. Now, since its an ecommerce website, we would be having dozens of products displayed, each having its own webpage. Now, my question is, if we have about 400 web pages on our server, won't it make the site pretty heavy and bulky? Won't that affect the user experience?
How can we manage the 400-odd web pages on Google App Engine? Is there something I don't know about making a web application less bulky in spite of hosting multiple web pages on the server?
You can use webapp2 framework and fetch product info from the datastore and render it with a template. You make an entity for your product e.g.
class Product(db.Model):
tags = db.ListProperty(db.Category)
category = db.CategoryProperty(verbose_name='Category')
title = db.StringProperty(verbose_name='title') # required
text = db.TextProperty(verbose_name='text')
Then you have a handler class using webapp2, flask, bottle or similar to fetch your product data and render it with for instance the jinja 2 templating engine.
class ProductHandler(BaseHandler):
def get_product(self, key):
data = memcache.get(key)
if data is not None:
return data
else:
data = Product.get_by_id(long(key))
memcache.add(key, data, 6000)
return data
def get(self, id, html):
product= self.get_product(id)
if not product:
self.error(404)
return
self.render_jinja(
'view_product',
product=product)
Then in your template you can use the variables on the view_product.html e.g.
{{product.title}
And the routing is done with a config object for webapp2 (this will be different if you use flask or bottle but if you use flask or bottle you can't leverage webapp2's extras such as User models and i18n)
app = webapp2.WSGIApplication([('/view/(\d+)(\.html?)?', ProductHandler),

Python Pyramid: Load view based on database variable

I just started pyramid and have a problem with loading views. I want to load a view based on a variable fetched from the database like my PHP solution here: rewrite url with htaccess
I've build a script that can do this, but I'm quite sure this is not the right way to do it. I think when I use this in a real site it will get very complicated and messy. Could someone explain how to this properly or point me to an other solution?
My current script:
config.add_route('home', '/')
config.add_route('admin_home', '/admin')
config.add_route('admin_pages', '/admin/pages')
config.add_static_view(name='static', path='website:static')
config.add_route('view_loader', '/*url')
views.py
class ViewLoader(object):
def __init__(self, request):
self.request = request
#view_config(route_name="view_loader", renderer="templates/view_loader.pt")
def view_loader(self):
request = self.request
url = "/%s" % request.matchdict["url"]
page = DBSession.query(Pages).filter_by(url=url).one()
return dict(title=page.title, include=page.template)
view_loader.pt
<!DOCTYPE html>
<html>
<body>
<metal:main use-macro="load: ${include}"></metal:main>
</body>
</html>
Idea of the system:
Admins can create pages in a cms with random url's and have to select a template. The system has to generate these pages.
url = /random/random -> look for template in db -> render template_1
url = /random2/random2 -> look for template in db -> render template_2
So I want to render the template after the class/method is being called to determine what template has to be rendered
I found a more logical approach for my problem with the help of this question Map different URLs to same view. Actually the solution is quite simple I just didn't know it is possible to declare a renderer in add_view()
main.py
pages = DBSession.query(Pages)
for page in pages:
config.add_route(str(page.name), page.url)
if page.template.decode('utf-8') == "home_view":
config.add_view(home_view, route_name=str(page.name), renderer='templates/home.pt')
elif page.template.decode('utf-8') == "detail_view":
config.add_view(home_view, route_name=str(page.name), renderer='templates/detail.pt')
views.py
def home_view(self, request):
return dict(.....)

Categories

Resources