Is there was a easy way to validate unique elements in a user entered form? I found ways to do it in php(lookup values after user enters it in table) but not sure how to do it using jinja2
For example, say a user is signing up and I require all email addresses to be unique, how can I let them know its not unique before they submit the results(like this: https://github.com/signup/free if you are already a member if you enter your email it'll tell you it exists as soon as you go to the next line. I've seen many sites do this)? Right now I can catch the errors but it refreshes the page and gives them an error and I'd like to let them know their form will fail before they hit submit. In this example, I'm checking for something that does not exist but in some other examples I'll want to check if something in the database exists.
I understand I'll need to query my database but I'm unsure how to do it from the template itself or if there's another way to do it.
You can do an XMLHttpRequest ( https://developer.mozilla.org/en/using_xmlhttprequest ) with Javascript to POST the input box's text (even easier if you use jQuery, as in the upcoming example) and do a DB query server-side to see if the email (input box text) is unique. Accordingly, you would return a response from this view, where xhr=True in the #view_config() decorator for non-IE browsers and request.response.content_type='text/html' is set for IE browsers. For example:
#view_config(permission='view', route_name='check_email', renderer='json') ##for IE browsers
#view_config(permission='view', route_name='check_email', renderer='json', xhr=True) ##for non-IE
def check_email(request):
email= request.POST['email']
dbquery = DBSession.query(User).filter(User.email==email).first()
## if the email exists in the DB
if dbquery:
msg = 'used'
## else if the email is available
else:
msg = 'available'
if request.is_xhr:
return {'msg':msg}
else: # for IE browser
request.response.content_type = 'text/html'
return Response(json.dumps({'msg':msg}))
You can do a POST easily (client-side) by using a library such as jQuery to take care of the XMLHttpRequest. After including the jQuery library in your template, as well as the .js file with you script:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script type='text/javascript' src="{{request.static_url('tutorial:static/myscript.js')}}"></script>
And then in myscript.js do:
$(function() {
$('#email').on('blur', postEmail)
})
// this function POSTs the entered email
function postEmail() {
var email = $(this).val()
$.post('/check_email', email, callback)
}
// this function is used to do something with the response returned from your view
function callback(data) {
if (data['msg'] === 'used') {
alert('used')
}
else if (data['msg'] === 'available') {
alert('available')
}
}
Instead of using javascript or Jquery, you could do a message system, passing it to the renderer through a dict. For example:
message = ''
if 'form.submitted' in request.params:#form.submitted being the name of the submit of the form
#check if email exists
if exists:
message = 'email already registered'
else:
message = 'success'
return dict(message = message)
Just a way of doing it without the JS
Related
I use software that only lets me fetch information on all users, while my project requires me to get only one specific user. I only need his ID and I'm going to find it out by his e-mail (because it's unique).
The program creates an user (via POST) and stores his data (like email) in variables, then reads a provided list of devices that will be assigned to said user. To do this, the program has to:
Fetch all users (why software author didn't allow to fetch a single user is beyond me)
Filter users so it finds my newly created user <- here's my issue
Fetch all devices...
Filter devices...
Finally create a permission relationship between found user and device IDs
This is what I came up with so far:
inputText = self.imeiInput.GetValue().splitlines() # reads input and creates a list
url = "https://example.com/api/users/"
userList = requests.get(url, auth=(login, password)).content
foundUser = re.findall(givenMail, str(userList)) # givenMail provided by function argument
print(userList)
print(foundUser) # prints only searched mail
for imei in inputText:
self.TrackerAssign(imei, foundUser) # do your stuff
But it only confirms that there indeed is my email in the userbase, there's no other info (like ID I'm interested in). Here's a sample userList output (except that originally it's all in one line):
b'[{
"id":1,
"attributes": {
...
},
"name":"username",
"login":"",
"email":"test#example.com",
"phone":"999999999",...
},
{
"id":2,
"attributes": {
...
},
"name":"username2",
"login":"",
"email":"test2#exmaple.com",
"phone":"888888888",...
},
...]'
Then there's also a question how to only read the desired ID. Sorry if this is confusing, I barely know what I'm doing myself.
From your example it seems like you get a JSON response from the endpoint. This is great, because this JSON can be parsed to a list/dictionary!
Your approach can look something like this. In broad terms, this is a possible strategy:
Get all users from the users endpoint.
Parse the response JSON to a list of dictionaries.
Loop over all users, breaking the loop when you find your user.
Do something with the ID of the user that you found in your search.
response = requests.get(url, auth=(login, password)) # receive a Response instance
user_list = response.json() # parse the body to a dictionary
for user in user_list:
# Compare the email of this user with the target, using get to catch users with no email specified.
if user.get("email") == given_mail:
desired_user = user
break # if we find the correct user, we exit the loop
else:
# If we never find the desired user, we raise an exception.
raise ValueError("There is no user with email %s", given_email")
print(f"The ID of the user I am looking for is {desired_user["id"]}.")
I have a button the user can press, it calls a function and nothing can happen until the function has finished executing. Is it possible to let the user press the button, call the function, but continue using the site and when the function has returned its output let the user know.
#app.route('/run_probe', methods=['POST'])
def run_probe():
if request.method == 'POST':
input_directory = request.form['directory']
if os.path.isdir(input_directory):
files = get_file_list.probe(input_directory)
return render_template('index.html', files=files)
else:
flash('Could not probe directory')
return redirect(url_for('index'))
This lets the user enter a directory/filepath into an <input> then it scans the directory and returns a list of filepaths. But this needs to finish befor the user can go anywhere else.
It would be nice if the user could run the function and do something else and when the function is done, return some sort of notication. Or even just a visual status.
I was thinking instead of directly returning a list, send the output to a mongodb for later retrieval, but if I hit run it still needs to do os.walk() before letting me continue.
You may need to use Javascript for that:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
const Url="http://host:port/to/your/time/consumming_function";
$("#button").on('click', function() {
$.ajax({
type:'GET',
url = Url,
success: function(data) {
//Update your document here or redirect
}
)}
return false; //Avoid auto reloading
}
</script>
The main idea is Ajax will request your Flask app. Then it will call function in success when it will finish. At this moment, update the content or redirect the user. The user will be able to continue on the same webpage while the ajax request is still running.
I just want to prevent you that you can get a timeout error if your task is too long. You may specify a timeout.
I have two different pages, one (A) that displays data taken from a model object, and one (B) that changes its fields.
I would like that when the post data is sent from B to the server, the server changes the values in A.
What is the best way to do it?
This example could work for me but it's in PHP... there is a way to replicate it whit Python?
https://www.w3schools.com/html/html5_serversentevents.asp
This is working example from w3schools in Django:
template
<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("stream/");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
views
import datetime
import time
from django.http import StreamingHttpResponse
def stream(request):
def event_stream():
while True:
time.sleep(3)
yield 'data: The server time is: %s\n\n' % datetime.datetime.now()
return StreamingHttpResponse(event_stream(), content_type='text/event-stream')
urls
urlpatterns = [
path('stream/', views.stream, name='stream')
]
Update:
If you want to manage your notifications you can create the model like:
from django.db import models
class Notification(models.Model):
text = models.CharField(max_length=200)
user = models.ForeignKey(User, on_delete=models.CASCADE)
sent = models.BooleanField(default=False)
Then create the view that is looking for the first unsent notification and sends it:
#login_required
def stream(request):
def event_stream():
while True:
time.sleep(3)
notification = Notification.objects.filter(
sent=False, user=request.user
).first()
text = ''
if notification:
text = notification.text
notification.sent = True
notification.save()
yield 'data: %s\n\n' % text
return StreamingHttpResponse(event_stream(), content_type='text/event-stream')
And the send_notification function that creates an entry in the Notification model (just call this function from anywhere in your code):
def send_notification(user, text):
Notification.objects.create(
user=user, text=text
)
After reading this, I think I understood the whole thing (please comment if I’m wrong).
Django does NOT natively support keep-alive connections.
This means, when the client gets the message from the server, the connection is immediately closed after (like any classic HTTP request/response cycle).
What’s different with text/event-stream request, is that the client automatically tries to reconnect to the server every second (the length can be changed with a retry parameter).
Unfortunately, it seems using SSE in that case has no interest since it has the same con’s that polling (ie. a request/response cycle occurs each X seconds).
As expected and mentioned in other answers, I would need django-channels to create a persistent connection that prevent HTTP request/response overheads and ensure the message is sent immediately.
As mentioned in other answers, you will need to use Django Channels to properly handle asynchronous communication without tying up threads.
For an example, see the django-eventstream library which uses Channels to implement SSE.
I am trying to set up a instagram plugin on django cms to show my recent images on a homepage by the username set in the plugin. It seems you can no longer simply get public content from instagram. This is the current method im using with my sandbox account.
user_request = requests.get("https://api.instagram.com/v1/users/search?q=" + str(instance.username) + "&access_token=" + settings.INSTAGRAM_ACCESS_TOKEN)
user_id = user_request.json().values()[1][0]["id"]
r = requests.get("https://api.instagram.com/v1/users/"+ user_id +"/media/recent/?access_token=" + settings.INSTAGRAM_ACCESS_TOKEN + "&count=" + str(instance.limit))
recent_media = r.json()
The code above gets the username from the plugin model and makes a get request to the instagram api to get that user (i've heard this method doesn't always show the correct user as its just searching and getting the first user from a list).
Is this the right way to work with the instagram api and python, I was going to use python-instagram but that is no longer supported. The only other way i can think of doing it is authenticating the user on the site and using their access token which seems silly for what i need it for.
EDIT:
Would removing the username field and adding access_token instead be a better method ? Then use "/users/self/media/recent" and rule out the query to search for a user by username.
Yes, the first results is not always the match, you have loop through all the search results and compare the username to your searched username, and then get id
Something like this:
var user_id = 0;
user_request.json().values()["data"].forEach(function(user){
if(user.username == str(instance.username)){
user_id = user["id"]
}
});
if(user_id){
// make api call
} else {
// user not found
}
Right now I am writing a snippet allowing submitting code to http://www.spoj.com/ from command line, i.e. something like python spoj_cl.py test.cpp
I understand that I need to send a POST request to the corresponding URL with specified parameters and cookie, but I'm still confused on which parameters to include on. Right now I'm doing it in a trial-and-error method, which seems not to be very effective. My questions are:
How to check systematically which parameters to be included in when sending a POST request?
How can I check immediately if the POST request I send is successful? One way I could think of is to get the content of the submission page http://www.spoj.com/status/, but checking the request directly should be preferable.
Below is the snippet I'm working on. Hopefully it should be readable.
import requests, sys
# if __name__ == "__main__":
base_url = "http://spoj.com"
autologin_hash = "*************" # Your user hash, taken from cookie
autologin_login = "************" # Your user name
session_id = "************" # Login session, can be retrieved when logged in
cookies_info = {
"autologin_login": autologin_login,
"autologin_hash": autologin_hash
}
ext_id = {
"cpp": "1"
}
filename = "test.cpp"
problem_name = str(filename.split(".")[0]).upper()
extension = filename.split(".")[1]
submit_url = base_url + "/submit/"
parts = {
"PHPSESSID": session_id,
"action": "/submit/complete",
"file": open(filename, "rb"),
"subm_file": "",
"lang": ext_id[extension],
"problemcode": problem_name
}
requests.post(submit_url,
params={"PHPSESSID": session_id},
files=parts,
cookies=cookies_info)
print "Submission sent!"
How to check systematically which parameters to be included in when sending a POST request?
I am not a member of the site spoj.com, but what you are asking for is basic web scraping. Find the HTML form for submitting code on the website, then use Firebug or Chrome developer console to find the HTML input elements with name attributes. Once you have found them, you can make a Python script to check for these elements systematically. If one day the elements are missing, the page probably changed.
Example Code:
webpage = requests.get(form_url, params={"PHPSESSID": session_id}, cookies=cookies_info)
html = BeautifulSoup(webpage.text)
form = html.find('form')
inputs = form.findAll('input')
names = []
for i in inputs:
names.append(i['name'])
How can I check immediately if the POST request I send is successful?
Check the status code of the response. It should be 200 for successful requests.
# Make the request
r = requests.post(submit_url,
params={"PHPSESSID": session_id},
files=parts,
cookies=cookies_info)
# Check the response code
if r.status_code == '200':
print "Submission successful!"
else:
print "Submission met a status code of: %s" % r.status_code