How to obtain the image path/ url from a file uploaded on an openshift data dir to be stored in a postgresql database? - postgresql

I am a self-taught programming newbie here so please bear with me. I am trying to create a site which allows users to upload their images on. With the patience of another user, I was able to get some answers as to how to create and allow users to upload their images onto the data drive on openshift. However, now I need to be able to store the image path or url onto a postgresql database (which can be called on later) so that each user will be able to keep track of the images that they have uploaded. I am currently stymied by this.
Here are the fragments of code which I feel plays a big role in answering this question:
class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column('todo_id', db.Integer, primary_key=True)
title = db.Column(db.String(60))
text = db.Column(db.String)
done = db.Column(db.Boolean)
pub_date = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('users.user_id'))
image_url = db.Column(db.String)
def __init__(self, title, text, image_url):
self.title = title
self.text = text
self.image_url = image_url
self.done = False
self.pub_date = datetime.utcnow()
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
#app.route('/upload', methods=['POST'])
def upload():
# Get the name of the uploaded file
file = request.files['file']
# Check if the file is one of the allowed types/extensions
if file and allowed_file(file.filename):
# Make the filename safe, remove unsupported chars
filename = secure_filename(file.filename)
# Move the file form the temporal folder to
# the upload folder we setup
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
# Redirect the user to the uploaded_file route, which
# will basicaly show on the browser the uploaded file
return redirect(url_for('uploaded_file',
filename=filename))
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
#app.route('/new', methods=['GET', 'POST'])
#login_required
def new():
if request.method == 'POST':
if not request.form['title']:
flash('Title is required', 'error')
elif not request.form['text']:
flash('Text is required', 'error')
else:
todo = Todo(request.form['title'], request.form['text'])
todo.user = g.user
db.session.add(todo)
db.session.commit()
flash('Todo item was successfully created')
return redirect(url_for('index'))
return render_template('new.html')
The current code that I have is pieced together by various tutorials and examples.
Currently, I am trying to merge the "Todo" db, "upload" function and "new" function and am having very little success. Using the little knowledge I have, I have merely added the "image_url" portions in which will be a column that is intended to house the image path. I would greatly appreciate it if somebody could shed some light on this conundrum. Thanks a million.
Respectfully,
Max

Related

Link content type to funtion on Telebot Python

I am building a Telegram Bot using telebot with python. I ask users to updload a picture, for which I created a command "foto". When they do /foto, I ask them to updload a content type "photo". However, they can upload pictures regardless of the command; they just click on upload a picture and that's it. How can I link the "upoload photo" to the command, so that they can only upload a picture after writing "/foto"?
#bot.message_handler(commands=['foto']) def send_welcome(message,
chat_id):
chat_id = message.chat.id
send = bot.send_message(message.from_user.id, 'SubĂ­ tu foto.')
bot.register_next_step_handler(send, photo())
return
#bot.message_handler(content_types=["photo"]) def photo(message):
fileID = message.photo[-1].file_id
logger.info("User_id, fileID", message.from_user.id, fileID)
file_info = bot.get_file(fileID)
#print('file.file_path =', file_info.file_path)
downloaded_file = bot.download_file(file_info.file_path)
with open(f"./images/{fileID}.jpg", 'wb') as new_file:
new_file.write(downloaded_file)
send = bot.send_message(message.from_user.id, 'Foto recibida, gracias!')
As far as i know you cant restrict users from sending files
what you can do is to capture the files only after the command is used
for more info please read docs

APScheduler update database only once

I'm trying to get APScheduler to update in my Flask app the Postgresql database every 5 minutes, but the database is only updated the first time, all subsequent times the changes are not saved. APScheduler itself works correctly, and if the function of updating the database is replaced with the function of displaying text, then everything works correctly every time.
In my app im using Flask-SQLAlchemy:
SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://postgres:name#localhost/name'
The APScheduler code looks like this:
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler(daemon=True)
sched.add_job(func=update, trigger='interval', minutes=5)
sched.start()
The database update function looks like this:
def update():
for i in data:
for row in Names.query:
if row.id == i['id']:
row.name = i['name']
row.gender = i['gender']
row.age = i['age']
db.session.commit()
In the logs, APScheduler always works successfully. I also looked at the Postgresql logs, where I found this phrase: 'An existing connection was forcibly closed by the remote host.'
I suspect it might be the database engine and sessions, but I haven't found the instructions I need to implement within the Flask-SQLAlchemy package.
Versions of pacages:
Flask-SQLAlchemy==2.4.1
SQLAlchemy==1.3.17
APScheduler==3.6.3
db Model:
class Names(db.Model):
__searchable__ = ['name', 'age']
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(40))
gender = db.Column(db.String(40))
age = db.Column(db.Numeric)
def __repr__(self):
return '<Names %r>' % self.id
I think I figured out what the problem is. APScheduler somehow caches the contents of a variable the first time it is used and then only uses that value.
Before the function, I have the following code:
request = requests.get('https://privateapi')
data = request.json()
Then the function takes data from data:
def update():
for i in data:
for row in Names.query:
if row.id == i['id']:
row.name = i['name']
row.gender = i['gender']
row.age = i['age']
db.session.commit()
According to the Flask-SQLAlchemy logs, the data is written to the database successfully. I tried adding to the print (data) function so that every 5 minutes it would show me the contents of the data variable and I saw that its contents were not updated.
It turns out that the data is written to the database, but with the same values, so I don't see its update.
Then I tried shortening the request path and not saving its content to a variable:
def update():
for i in requests.get('https://privateapi').json():
for row in Names.query:
if row.id == i['id']:
row.name = i['name']
row.gender = i['gender']
row.age = i['age']
db.session.commit()
But here again nothing has changed.
UPDATE:
I solved this problem by removing the data variable at the end of the function:
def update():
name = requests.get('https://privateapi').json()
for i in name:
for row in Names.query:
if row.id == i['id']:
row.name = i['name']
row.gender = i['gender']
row.age = i['age']
del name
db.session.commit()

BigBlueButton change branding dynamically on different conference without changing files every time

I have BigBlueButton hosted on one server, I need to organize multiple conferences, But I need different brandings like a logo and background color to change with every single conference, So is there any approach to do this thing with BigBlueButton?
You can change the background color dynamically by adding a query parameter (userdata-customStyle) in join meeting request url. You can see more parameters in the given link userdata parameters.
I'm using greenlight, so I'm sharing a block of code which dynamically set the background color and add it to the query parameter of 'join meeting URL', I think this will help you.
def join_path(room, name, options = {}, uid = nil)
# Create the meeting, even if it's running
start_session(room, options)
# Determine the password to use when joining.
password = options[:user_is_moderator] ? room.moderator_pw : room.attendee_pw
# Generate the join URL.
join_opts = {}
join_opts[:userID] = uid if uid
join_opts[:join_via_html5] = true
join_opts[:guest] = true if options[:require_moderator_approval] && !options[:user_is_moderator]
print "------------------------- Background color----------------------------- \n"
if room.background_color
bg_color = "body { background-color: "+ room.background_color.to_s
bg_color += "!important;}"
else
"body { background-color: #06172A !important;}"
end
print bg_color
join_opts[:"userdata-customStyle"] = bg_color
bbb_server.join_meeting_url(room.bbb_id, name, password, join_opts)
end

Iterate over files in random order

I am working on an educational script in swift. The aim is to facilitate collaboration between peers in a university level class on statistics. Each student is required to make suggestions (anonymously) to one of their colleagues' work. The script I have been writing works so that all markdown files in the directory are anonymized (ie, author and email yaml keys are removed) and new files with the contents are created and renamed with an email address.
So far I was able to remove author: and email: yaml keys from each file and I was also able to rename the files in the directory. However, I am struggling to create a way of randomizing files and emails. The point is that the original file should be passed on to another student, but without the last one knowing the author. The receiving student should be decided randomly. This randomization is what I am struggling with.
The MWE
It is a linux project and the easiest way I found to create a MWE was to write the script using the excellent John Sundell's marathon script structure. Below is the code:
import Yaml // marathon: https://github.com/behrang/YamlSwift.git
import Files // marathon:https://github.com/JohnSundell/Files.git
import Foundation
var email: String = ""
var document: String = ""
for file in Folder.current.files {
guard file.extension == "md" else {
continue
}
let content = try file.readAsString()
let pattern = "(?s)(?<=---).*(?=---)"
if let range = content.range(of: pattern, options: .regularExpression) {
let text = String(content[range])
let value = try! Yaml.load(text)
email = value["email"].string!
let author = value["author"].string!
let emailline = "email: " + email
let authorline = "author: " + author
document = content.replacingOccurrences(of: "\n\(emailline)", with: "")
document = content.replacingOccurrences(of: "\n\(authorline)", with: "")
}
// Creating new file with name from email and copying contents into it
//let folder = try Folder()
let file = try Folder.current.createFile(named: email)
try file.write(string: document)
}
An example md file:
---
# Metadata
title: hum
author: jecatatu
email: email#gmail.com
---
This is more text outside the yaml block
email: zwe#gmail.com
A second file:
# Metadata
title: My essay
author: brauser
email: brauser#gmail.com
---
Extra text
A third file:
# Metadata
title: My third essay
author: bestuser
email: bestuser#gmail.com
---
Extra text
Question
To start off, I don't need code. But code is welcome. Note that one can run the above example (provided you have marathon installed) with:
marathon run lf-araujo/collab
I guess I can solve this problem by iterating over the files in the directory in a random order. How can do that? My first thought was to create a dict with emails and filenames, and scramble these two.
What you need is a deterministic way of assigning one reviewer to one peer. You can achieve that by creating a two maps of (random -> article). Sort them by the random key and match the articles by index. An example in pseudo code:
/* Note that you may want to be sure that random keys are unique */
map reviewers = [random_integer(): article_one,
random_integer(): article_two,
...]
map articles = [random_integer(): article_one,
random_integer(): article_two,
...]
sort reviewers by key
sort articles by key
for (index in 0..length(reviewers)) {
assign_reviewer(author_from: reviewers[index], to: articles[index])
}

can't get pictures from gridFS using Tornado

my problem is that i can get the save picture to gridFS even if it's there, i've verified and it show me the piture and its name and the size from the console.
here is the code:
conn = Connection()
the classe that saves to the database:
class Profile(tornado.web.RequestHandler):
def post(self):
self.db = conn["essog"]
avat = self.request.files['avatar'][0]["body"]
avctype = self.request.files['avatar'][0]["content_type"]
nomfich = self.request.files['avatar'][0]["filename"]
#..operation using PIL to decide to save the picture or not
self.fs = GridFS(self.db)
avatar_id = self.fs.put(avat, content_type=avctype, filename=nomfich) #change the name later to avoid delete using the same name, so generating a different name...
.....
user={..., "avatar":avatar_id}
self.db.users.insert(user)
self.db.users.save(user)
the class that reads from the database:
class Profil(tornado.web.RequestHandler):
def get(self):
self.db = conn["essog"]
self.fs = GridFS(self.db)
avatar_id = self.db.users.find_one()["avatar"]
...
avatar = self.fs.get(avatar_id).read()
self.render("profile.html",..., avatar=avatar)
and in the view (profile.html)
img src="{{avatar}}" />
but nothing is displayed!
Unless you want to use a base64 URI for the source of the image, you should use a url and then create a view for returning the data from that view. If you are using nginx you might be interested in the nginx-gridfs module for better performance.
The src attribute of an img tag does not (typically) contain the image data itself, but rather the URL of the image. I think you're confusing two separate requests and responses:
HTML page that contains an <img src="..." /> tag:
class Profil(tornado.web.RequestHandler):
self.render('profile.html',
avatar=self.reverse_url('avatar', avatar_id))
image itself (which needs a separate handler):
class Avatar(tornado.web.RequestHandler):
def get(self, avatar_id):
avatar = self.fs.get(avatar_id)
self.set_header('Content-Type', avatar.content_type)
self.finish(avatar.read())