Django кэширует значение базы данных в функции представления
Я делаю приложение, которое позволяет пользователю захватить Google Sheet в виде изображения и отправить его в чат нашей компании в качестве оповещения. Я сохраняю учетные данные google sheet api в базе данных, и когда пользователь нажимает кнопку "Run" в веб-интерфейсе, это вызывает ajax-запрос, который запускает функцию в views.py, чтобы начать захват. Если срок действия учетных данных истекает, эта функция обновляется для получения новых учетных данных и обновления новых значений в базе данных.
Но проблема в том, что когда старые учетные данные истекают и заменяются новыми, функция в view.py все еще использует старые учетные данные в базе данных, поэтому она не работает из-за неправильных учетных данных. Я думаю, что причина в том, что Django кэширует старое значение в базе данных, но не знаю, как очистить кэш перед получением значения из базы данных.
У меня есть основное приложение под названием ggchat. Я использую docker, gunicorn, nginx и celery для развертывания этого приложения.
Моя функция в views.py:
...
from lib.custom import capture_gs
@login_required(login_url='/accounts/login/')
def run_task(request):
task_id = request.GET.get('task_id', None)
capture_gs(task_id)
...
Функция capture_gs - это локальный пакет, который получает или обновляет учетные данные из базы данных и захватывает лист google в виде изображения. Ниже приведен код для этого пакета:
from __future__ import print_function
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
import pandas as pd
import numpy as np
import requests
from mysite.models import Gstoken
from ggchat.models import Task
import datetime as dt
from lib.chat import upload_file
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
# Get token from db, create credential for gsheet oauth. If not found token from db, create db from file token.json
try:
gstoken = Gstoken.objects.get(email='abc@gmail.com')
creds = Credentials(token = gstoken.token, refresh_token=gstoken.refresh_token, token_uri=gstoken.token_uri, client_id=gstoken.client_id, client_secret=gstoken.client_secret, expiry = gstoken.expiry.replace(tzinfo=None), scopes=SCOPES)
except:
creds = Credentials.from_authorized_user_file('/app/lib/credentials/google/sheet/token.json', SCOPES)
# comment in first docker run
gstoken = Gstoken.objects.create(email='abc@gmail.com', token=creds.token, refresh_token=creds.refresh_token, token_uri=creds.token_uri, client_id=creds.client_id, client_secret=creds.client_secret, expiry = creds.expiry + dt.timedelta(hours=7))
# If token is outdated, refresh and update into db. If there are no (valid) credentials available, let the user log in.
if not creds.valid:
creds.refresh(Request())
# comment in first docker run
try:
gstoken.token = creds.token
gstoken.expiry = creds.expiry + dt.timedelta(hours=7)
gstoken.save()
except:
pass
def get_auth_token():
return creds.token
def get_pdf(spreadsheet_id, **kwargs):
"""
Return a screenshot pdf object from spreadsheet
"""
url = "https://docs.google.com/spreadsheets/d/" + spreadsheet_id + "/export"
params = {"format":"pdf", "vertical_alignment": "MIDDLE", "horizontal_alignment": "CENTER", "fzr": "false", "fzc": "false", "gridlines": "false"} # default params
params.update(kwargs)
headers = {"Authorization": "Bearer " + get_auth_token()}
return requests.get(url, params = params, headers = headers)
def capture_gs(task_id):
task = Task.objects.get(pk=task_id)
r = get_pdf(task.ss_id, gid = task.gid, range = task.gs_range, scale = 4)
pdf_file = '/app/temp/result.pdf'
with open(pdf_file, 'wb') as saveFile:
saveFile.write(r.content)
upload_file(channel_name=task.channel, message=task.message, file_path=pdf_file)
Поскольку все еще используется старая учетная запись, функция get_pdf возвращает поврежденный pdf файл с ошибкой 401 unauthorized.
Я решил эту проблему. На самом деле значение базы данных не кэшируется, но переменная creds кэшируется, поэтому после обновления она сохраняет то же состояние со старыми учетными данными. Поэтому я больше не получаю токен из переменной creds, а получаю его непосредственно из базы данных. Я немного изменил функцию get_auth_token:
def get_auth_token():
return Gstoken.objects.get(email='abc@gmail.com').token