简体   繁体   中英

How can I validate unique form elements in jinja2/pyramid/sqlalchemy?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM