So, basically i have a task managing application i am working on, and i need a way to detect if there's no tasks in the database so i can make a simple jinja2 format on it.
Here is my code:
#app.route("/dashboard")
def dashboard():
if "name" in session:
username = session['name']
ifTask = taskAdd.find({"name": username})
name = session['name']
tasknames = []
if ifTask is None:
return render_template('dashboard.html', noTasksDB=True)
for x in ifTask:
tasknames.append((x['taskname'], x['Priority'], x['Notfication']))
return render_template('dashboard.html', dashboardPage=True, title=name+"'s Dashboard", name=True, username=username, ifTask=ifTask, tasknames=tasknames, noTasksDB=False)
I tried to add the following code:
if ifTask is None:
return render_template('dashboard.html', noTasksDB=True)
I expected None to work, but it didn't instead the HTML remained the same .
I also tried printing ifTask when there are no current tasks in the database and all i get is some pymongo cursor which i have no idea on what it means.
Does anyone know how to fix this problem?
If you do as the other commenter suggested, but change your comparison a bit then this should work. ifTask will be an empty list if nothing is found - and then we just check if it's empty rather than comparing it to None.
ifTask = list(taskAdd.find({"name": username}))
if not ifTask:
return render_template('dashboard.html', noTasksDB=True)
or if you don't want to do that. Then
ifTask = taskAdd.find({"name": username})
name = session['name']
tasknames = []
for x in ifTask:
tasknames.append((x['taskname'], x['Priority'], x['Notfication']))
if not tasknames:
# tasknames is an empty list - no tasks
return render_template('dashboard.html', noTasksDB=True)
return render_template(
'dashboard.html',
dashboardPage=True,
title=name+"'s Dashboard",
name=True,
username=username,
ifTask=ifTask,
tasknames=tasknames,
noTasksDB=False
)
tasknames will be empty if taskAdd.find didn't find any results.
Related
So, while trying to code something, I saw this error, but I am not actually overwriting anything, at least from what I know. Can anyone help? Here is the full code
I don't know what really happened here, and I really need help quickly, please.
My friend also reviewed it and said he doesn't know what that means either, so I really wanted to fix it, I am writing this because I have to also put more text, but please help if you can, thank you!
import jsonify
from flask_jwt_extended import jwt_required
from api import db
blogs= Blueprint('blogs',__name__)
#blogs.route("/add_blog", methods=["POST"])
#jwt_required
def create_blog():
data = request.get_json()
new_blog=Blog(title=data["title"],content=data["content"],feature_image=data["feature_image"])
for tag in data["tags"]:
present_tag=Tag.query.filter_by(name=tag).first()
if(present_tag):
present_tag.blogs_associated.append(new_blog)
else:
new_tag=Tag(name=tag)
new_tag.blogs_associated.append(new_blog)
db.session.add(new_tag)
db.session.add(new_blog)
db.session.commit()
blog_id = getattr(new_blog, "id")
return jsonify({"id": blog_id})
#blogs.route('/blogs',methods=["GET"])
def get_all_blogs():
blogs= Blog.query.all()
serialized_data = []
for blog in blogs:
serialized_data.append(blog.serialize)
return jsonify({"all_blogs": serialized_data})
#blogs.route('/blog/<int:id>',methods=["GET"])
def get_single_blog(id):
blog = Blog.query.filter_by(id=id).first()
serialized_blog = blog.serialize
serialized_blog["tags"] = []
for tag in blog.tags:
serialized_blog["tags"].append(tag.serialize)
return jsonify({"single_blog": serialized_blog})
#blogs.route('/update_blog/<int:id>', methods=["PUT"])
#jwt_required
def update_blog(id):
data = request.get_json()
blog=Blog.query.filter_by(id=id).first_or_404()
blog.title = data["title"]
blog.content=data["content"]
blog.feature_image=data["feature_image"]
updated_blog = blog.serialize
db.session.commit()
return jsonify({"blog_id": blog.id})
#blogs.route('/delete_blog/<int:id>', methods=["DELETE"])
#jwt_required
def delete_blog(id):
blog = Blog.query.filter_by(id=id).first()
db.session.delete(blog)
db.session.commit()
return jsonify("Blog was deleted"),20```
I want to pass some arguments to my HTML form from flask when using redirect(url_for('Some End-Point')) instead of render_template(). I have already visited both of these questions
redirect while passing arguments
How can I pass arguments into redirect(url_for()) of Flask?
but neither of them had the answer I am looking for. After some surfing I do find out that I have to use session for this but the problem is I don't know actually how to use that either. When I use this:
return redirect(url_for('register', neg_resp="Username Already Taken"))
the problem was, my output message do generate but came with URL instead and thus my jinja template doesn't receive it. Link from 120.0.0.1:5000/register/ changed to 120.0.0.1:5000/register/?=Username Already Taken
And when I do this:
return redirect(url_for('register'), neg_resp="Username Already Taken")
An error gets generated, TypeError: redirect() got an unexpected keyword argument 'neg_resp'
Here's my Python Code
# Setting Up Route for Register Page
#app.route('/register/', methods=['GET', 'POST'])
def register():
# Fetching Form Data
user = {
"name": request.form.get('name'),
"email": request.form.get('email'),
"username": request.form.get('username'),
"password": request.form.get('password'),
"tasks":[]
}
# Inserting data to Database and Redirecting to Login Page after Successful Registration
if user['name'] != None:
user['password'] = pbkdf2_sha256.encrypt(user['password'])
if mongo.db.appname.find_one({"username": user["username"]}):
return redirect(url_for('register'), neg_resp="Username Already Taken")
else:
mongo.db.appname.insert(user)
return redirect(url_for('login', pos_resp="Registered Successfully"))
return render_template('register.html')
Error
TypeError: redirect() got an unexpected keyword argument 'neg_resp'
This won't work:
return redirect(url_for('register'), neg_resp="Username Already Taken")
because it passes neg_resp as a parameter of redirect instead of url_for.
Here's a basic example of how to pass parameters between routes and to a template:
#app.route('/first/')
def first():
return redirect(url_for('second', passed_value='string value'))
#app.route('/second/')
def second():
passed_value = request.args.get('passed_value')
return render_template('index.html', val_name=passed_value)
So here's what I tried, I made a global dictionary and keep updating it wherever needed, now whenever I want to access some values I directly access it from my dictionary and render it using jinja templating. Apart from this method there are other ways as well like storing data in flask.session also one can use flask.flash() to render messages and access them using messages.get() function in their jinja template, but the problem with it is, it only provides a limited amount of size, if you pass an object or string of beyond that size, the browser simply ignores it and your messages will not be displayed because the message passed is in the form of browser-cookies. So, storing them in my global dictionary works for me:
Here's a small snippet of my final code which similarizes the code I have posted as question:
# Globals
info = {
'logged_in' : False,
'user' : {},
'tasks' : [],
'status' : {
'value' : '',
'positive' : True
}
}
def reset():
'''
function to reset the values of info object
'''
global info
info['logged_in'] = False
info['user'] = {}
info['tasks'] = []
info['status'] = {
'value' : '',
'positive' : True
}
# Setting Up Route for Register Page
#app.route('/register/', methods=['GET', 'POST'])
def register():
'''
function to register an account into the server and database
'''
global info
# Fetching Form Data
user = {
"name": request.form.get('name'),
"email": request.form.get('email'),
"username": request.form.get('username'),
"password": request.form.get('password'),
"tasks":[]
}
# Inserting data to Database and Redirecting to Login Page after Successful Registration
if user['name'] != None:
user['password'] = pbkdf2_sha256.encrypt(user['password'])
if mongo.db.appname.find_one({"username": user["username"]}):
info['status']['value'] = 'Username Already Taken'
info['status']['positive'] = False
return redirect(url_for('register'))
else:
mongo.db.appname.insert(user)
info['status']['value'] = 'Registered Successfully'
info['status']['positive'] = True
return redirect(url_for('login'))
status_val = info['status']['value']
positive_status = info['status']['positive']
reset()
return render_template('register.html', value = status_val, positive = positive_status)
With Flask-Admin and Flask how can I submit a form\view based on ModelView from code?
I'm trying to create a separate view\form that would allow user to add multiple entries with one form. Specifically allowing to upload multiple images with common prefix name and common parameters. I'd like to do it by submitting a single-image upload form from code, because it does some additional processing like resizing images and I'd like to let Flask-Admin handle connecting database entries and files.
Here's the form I'd like to submit from code:
class ImageView(ModelView):
def _list_thumbnail(view, context, model, name):
if not model.path:
return ''
return Markup('<img src="%s">' % url_for('media',
filename=form.thumbgen_filename(model.path)))
column_labels = dict(show_in_header="Show In Header?",
path="Image")
form_create_rules = ("name",
"tags",
rules.Text(
"Use this image as header. If more than one image is selected header image will be random each time the page is loaded."),
"show_in_header",
"path")
form_excluded_columns = ("timestamp")
column_formatters = {
'path': _list_thumbnail
}
thumbnail_size = config("media", "thumbnail_size")
form_extra_fields = {
'path': BroImageUploadField('Image',
base_path=IMAGES_FOLDER,
thumbnail_size=(thumbnail_size, thumbnail_size, True),
endpoint="media",
url_relative_path='media',
relative_path=None)
}
def is_accessible(self):
return current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# redirect to login page if user doesn't have access
return redirect(url_for('login', next=request.url))
And here I'm creating a form and I'm just not sure that .process() is the function to submit it? Is there one at all?
lass MultipleImagesUploadView(BaseView):
#expose("/", methods=["GET", "POST"])
def index(self):
if request.method == "POST":
a_form = MultipleImagesForm(request.form)
base_name = a_form.base_name.data
tags = a_form.tags.data
show_in_header = a_form.show_in_header.data
print (request.files.getlist(a_form.images.name))
uploaded_files = request.files.getlist(a_form.images.name)
for i, uf in enumerate(uploaded_files):
try:
name, ext = os.path.splitext(uf.filename)
if ext not in IMAGE_EXTENSIONS:
flash("Image file {} was skipped as it's extension is not supported ({}).".format(uf.filename, ext), category="warning")
continue
image_contents = uf.stream.read()
image_form = ImageView()
image_form.name.data = "{}_{}".format(base_name, i)
image_form.tags.data = tags
image_form.show_in_header.data = show_in_header
image_form.path.data = image_contents
image_form.process()
except Exception as e:
flash ("Unhandled exception: {}".format(e), category="warning")
flash("Images were added to the gallery.", category='success')
a_form = MultipleImagesForm()
print("############", a_form)
return self.render('/admin/multiple_images_upload.html', form=a_form)
I can't figure out a way to submit a form from code, been trying to find the answer in docs and google for hours now with no luck.
Found the issue. In my case I was missing the enctype="multipart/form-data". Without that files part was sent as empty.
Also changed to using from flask_wtf import FlaskForm and enabling it as {{ form.files(class="form-control", multiple="") }} in the template.
Files can then be accessed with uploaded_files = request.files.getlist("files") on POST request, it will hold array of file-objects.
I hope this helps someone. If any additional formatting is required I will add or expand the answer.
I am working in a small website where I want to show, insert, edit and delete elements from the database
I accomplished showing the data with this route:
#app.route('/objects')
def objects():
g.db = sqlite3.connect(db_location)
cur = g.db.execute('SELECT * FROM milkyway ORDER BY type')
objects = [dict(id=row[0], type=row[1], name=row[2], description=row[3], size=row[4], mass=row[5],distance=row[6], discoverer=row[7], image_url=row[8]) for row in cur.fetchall()]
g.db.close()
return render_template("objects.html",objects=objects)
And now I am trying to insert an element but I receive an error "AttributeError: '_AppCtxGlobals' object has no attribute 'db'"
#app.route('/insert_value',methods = ['POST', 'GET'])
def insert_value():
atype = request.form['type']
name = request.form['name']
description = request.form['description']
size = request.form['size']
mass = request.form['mass']
distance = request.form['distance']
discoverer = request.form['discoverer']
image_url = request.form['image_url']
g.db.execute('INSERT INTO milkyway (type,name,description,size,mass,distance,discoverer,image_ur) VALUES (?,?,?,?,?,?,?,?)', [atype], [name], [description], [size], [mass], [distance], [discoverer], [image_url] )
g.db.commit()
return redirect(url_for('objects'))
I search everywhere but the thing is, there are so many different ways to do this and I cannot make it works. I followed for instance this example; http://opentechschool.github.io/python-flask/extras/databases.html
The connection, g.db, needs to be added with each request. You only create it in objects, so it doesn't exist for insert_value. g is an object which is created in the context of each request.
As the example code shows, you should create the connection before each request and add it to g.
#app.before_request
def before_request():
g.db = sqlite3.connect(db_location)
Be sure to also close it in #app.teardown_request.
first of all i'm sorry because of my duplicated question but actually the other didn't work for me at all.
my problem is that I have 2 views which the first one is returning a Httpresponse to the 2nd, and what I want is to convert this Httpresponse to dictionary in the 2nd view and have access to it's elements.
here is the code :
1st view:
def base_tag_upload(request, tag):
error = False
upload_msg = "success"
user = request.user
response_data = {"error": error, "upload_msg": upload_msg, "file_id": None, "file_version": None}
if request.method == 'POST':
form = UploadForm(request.POST or None, request.FILES or None, tag=tag, user=user)
if form.is_valid():
cd = form.cleaned_data
uploaded_file = cd['file']
collection_name = cd['new_name'] or uploaded_file.name.split('.')[0].strip()
response_data.update(
{"uf_name": uploaded_file.name, "uf_size": uploaded_file.size, "uf_colname": collection_name})
set_primary = True # first file in collection
# Finding/Creating Related FileCollection
collection = FileCollection.objects.create(name=collection_name)
is_major = cd['version_type'] == 'mj'
file_obj = collection.upload_file(uploaded_file, set_primary, Major_version=is_major)
file_obj.author = user
collection.tags.add(tag)
collection.get_tag_permissions(tag, False)
file_obj.get_collection_permissions(collection, False)
set_user_ownership(collection, tag, user)
set_user_ownership(file_obj, tag, user)
collection.save()
file_obj.collection = collection
file_obj.save()
response_data.update({'file_id':file_obj.id, 'file_version': file_obj.version})
ActionLog.log(action=Action.objects.get(name="create"), target=file_obj,
user=user, request=request, details=None, extra_details=None)
redirect_url = reverse('file_history', kwargs={'collection_id': collection.id})
response_data.update({'redirect': redirect_url})
return HttpResponse(json.dumps([response_data]))
and the 2nd one :
def tag_upload(request, tag_id):
try:
tag = Tag.objects.get(id=tag_id)
except Tag.DoesNotExist:
return HttpResponse(simplejson.dumps([{'error': 'value_error', 'upload_msg': "no such folder"}]))
k = base_tag_upload(request, tag)
k.response.decode('utf-8')
print k
return base_tag_upload(request, tag)
but I got this error when I wanted to decode the Httpresponse as shown above :
AttributeError: 'HttpResponse' object has no attribute 'response'
I have 2 views which the first one is returning a Httpresponse to the 2nd
Then you didn't structured your code properly - a view has no business calling another view not messing with the response.
If you need to share some common code between two views, then extract this code in a distinct function (that would in this case return a plain dict) and call this function from both your views.
It's k.content.decode('utf-8').