javascript - Making an AJAX request to a Django view that may require a redirect? -


introduction

i getting error when trying request particular django view ajax. view redirects user if have not yet authorized site google. believe problem lies in fact trying perform redirect "within" view requested ajax. read on more information, , in advance help!

background information

i wrote view in django called export_to_drive uses google drive api , returns json.

@gauth_required(scope='https://www.googleapis.com/auth/drive.file') def export_to_drive(request, credential, sheet_id):     """     export sheet google drive.     """     http = credential.authorize(httplib2.http())     service = build('drive', 'v3', http=http)      # ...      new_file = service.files().create(body=file_metadata,                                       media_body=media,                                       fields='webviewlink').execute()      return jsonresponse(new_file) 

this view requires user give site permission add files google drive on behalf. in order ensure user has authorized site google, wrote decorator called gauth_required.

def gauth_required(scope):     """     decorator requires user authenticate     google , authorize site act on behalf.     if user has authenticated, call wrapped function     kwarg `credential` set obtained credentials.     if not, start oauth 2.0 flow.     @ moment, used sheets.views.export_to_drive.     """     def wrapper(func):         @login_required         @wraps(func)         def inner(request, *args, **kwargs):             storage = storage(credentialsmodel, 'id',                               request.user, 'credential')             credential = storage.get()              if credential none or credential.invalid:                 request.session['next_view'] = request.path                 return httpresponseredirect('/gauth?scope={}'.format(scope))              kwargs['credential'] = credential             return func(request, *args, **kwargs)         return inner     return wrapper 

as can (hopefully) see, decorator checks see if there stored credential object given user , if not, start oauth 2.0 authentication flow obtain one. not believe relevant question (and in effort refrain scaring away potential answerers enormous amounts of code), i'm choosing not show code flow. real important detail know requires several redirects (this come later).

the problem

the export_to_drive view being accessed via jquery ajax call client-side javascript.

function exporttodrive() {     $.post("/api/sheets/" + sjs.current.id + "/export_to_drive", function(data) {         if ("error" in data) {             sjs.alert.message(data.error.message);         } else {             sjs.alert.message("source sheet exported google drive.<br><br><a href='" + data.webviewlink + "'>open in google drive &raquo;</a>");         }     }) } 

when attempt click on ui element function bound to, following error in console if there no credential on-file signed in user.

xmlhttprequest cannot load https://accounts.google.com/o/oauth2/auth?state=zdschtkbh_t7iosyl5cpvdoxndy…e=https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.file&access_type=offline. no 'access-control-allow-origin' header present on requested resource. origin 'http://localhost:8000' therefore not allowed access. 

when go directly export_to_drive endpoint in browser, works dandy, regardless of whether credential retrieved storage or created oauth 2.0 flow. therefore, have hunch problem lies in needing perform redirect complete authorization flow within ajax request.

the question(s)

  • is possible perform redirect requested ajax url? if not, there way refactor code make work without needing that?
  • has dealt or similar before?
  • is suspicion off-base , else entirely causing error?

i had similar problem while trying sync contacts on google , start whole process client side. managed work around returning redirect url (instead of doing httpresponseredirect) , redirecting jquery.

so, instead of return httpresponseredirect('/gauth?scope={}'.format(scope)) return json: {'redirect_url': '/gauth?scope={}'.format(scope)} , on client side:

if ("error" in data) {     sjs.alert.message(data.error.message); } else if ("redirect_url" in data) {     // if you're returning same page, need post export api again     window.location.replace(data.response.redirect_url); } else {     sjs.alert.message("source sheet exported google drive.<br><br><a href='" + data.webviewlink + "'>open in google drive &raquo;</a>"); } 

a problem still remains: after redirect oauth , user authorizes operation page , should try export again. in order figure out need try again could:

  • set cookies when redirect , check them when page loads (after authorization)
  • pass in parameter url oauth use return after authorization (you should able modify url in python, verify parameter on client side , restart export process)

i started working python/django few months ago i'm not sure best solution (another 1 whole oauth process on client side - never tried it) hope helps. if managed solve problem in way, grateful if share insight.