需要有关pyqt logout

时间:2017-07-21 10:32:05

标签: python django qt

我有PyQt5应用程序的问题,不知道如何解决它。

在我的托盘qt应用程序中,我有用户注销操作按钮,该按钮与注销功能相关联。 tray.py 中的退出功能应通过 views.py 中的服务器应用上的响应我的退出功能来激活。在 views.py 中,我有退出httpResponse的退出功能(“用户已注销”)。

我的问题是:“当用户按下该注销按钮时,如何识别我的桌面pyqt应用程序?因为我收到response.status_code = 200它只表示我只收到一个页面,而不是那个用户状态(如果用户是登录或注销)“。一切似乎都没问题,但不知道如何在 tray.py / logout()

中继续执行代码

桌面应用 - tray.py

import json
import sys, os, requests, uuid

from Crypto import Random
from Crypto.PublicKey import RSA
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QMenu
from PyQt5.QtWidgets import QSystemTrayIcon

from login import LoginForm
from settings import HTTP_PROTOCOL
from settings import SERVER_URL
from timestamp.form import TimestampForm



class SystemTrayIcon(QSystemTrayIcon):

    def __init__(self):
        QSystemTrayIcon.__init__(self)

        self.setIcon(QIcon('icons/icon-placeholder_128x128_red.png'))

        self.http_client = requests.Session()
        self.base_url = '{}://{}'.format(HTTP_PROTOCOL, SERVER_URL)
        self.set_desktop_timezone()


        # Keeping reference to LoginForm object so that window wouldn't close




        self.uuid = self.create_uuid('TTASM')
        self.create_private_key()

        try:
            requests.get(self.base_url)
            self.server_accessible = True
            self.present_login_form()
        except:
            self.server_accessible = False
            pass

        self.set_server_public_key()

        self.create_ui()

    def createURL(self, path):
        return '{}{}'.format(self.base_url, path)

    # Find Desktop's timezone   
    def set_desktop_timezone(self):
        response = requests.get('http://freegeoip.net/json')
        response_json = json.JSONDecoder().decode(response.text)
        self.timezone = response_json['time_zone']

    def verify_initial_data(self):
        url = self.createURL('/initial_synchronization/?timezone={}'.format(self.timezone))
        try:
            response = self.http_client.get(url)
            if response.status_code == 200:
                self.last_timestamp = response.text
            else:
                raise Exception('Server errror: {}'.format(response.status_code))
        except:
            print('Something is wrong with server comms')

    def set_server_public_key(self):
        #get server public key 

        url = self.createURL('/public_key/')
        print('Trying to get the public key from:', url) 

        try:
            response = self.http_client.get(url)
        except:
            print ('No response, server may be down')

        try:
            if response.status_code == 200:
                self.server_rsa_pub  = RSA.importKey(response.text)
                print ('Server private key aquired')
            else:
                print ('Server failed to provide public key')
        except:
            print("\nServer is not responding")
#             self.loginForm.close()

    def create_private_key(self):
        #Create new client RSA private key, public key and public key hash and store them to disk
        random_generator = Random.new().read
        self.client_rsa = RSA.generate(2048, random_generator)
        print ('Client private key created')

#         with open('./clientdata/client_RSA', 'wb') as f:
#             f.write(cl_rsa.exportKey())
#         with open('./clientdata/client_RSA.pub', 'wb') as f:
#             f.write(cl_rsa.publickey().exportKey())
#         with open('./clientdata/client_RSA.hash', 'w') as f:
#             f.write(SHA256.new(cl_rsa.publickey().exportKey()).hexdigest())

    print ('Client keys created')

    def create_ui(self):
        """Create user interface of Tray icon"""

        mainMenu = QMenu()
        subMenu = QMenu(mainMenu)
        subMenu.setTitle("Util")
        subButton_1 = subMenu.addAction("Show token")
        subButton_1.triggered.connect(self.show_token)
        subButton_2 = subMenu.addAction("Test sockets")
        subButton_2.triggered.connect(self.test_sockets)

        # Set the order of layout and add everything to main menu
        self.logInButton = mainMenu.addAction("Log in")
        self.logInButton.triggered.connect(self.present_login_form)

        self.simButton = mainMenu.addAction("Let's pretend server is accessible")
        self.simButton.triggered.connect(self.enable_login_etc)


        mainMenu.addSeparator()
        self.msgButton = mainMenu.addAction("Send message") # find a way how to hide this button to preserve action on it before user's log in action
        self.msgButton.triggered.connect(self.present_timestamp_form)

        if not self.server_accessible:
            self.logInButton.setEnabled(False)
            self.msgButton.setEnabled(False)


        mainMenu.addSeparator()
        mainMenu.addMenu(subMenu)
        mainMenu.addSeparator()
        self.logoutButton = mainMenu.addAction("Log out")
        self.logoutButton.triggered.connect(self.logout)
        self.logoutButton.setEnabled(False)
        mainMenu.addSeparator()
        exitButton = mainMenu.addAction("Exit")
        exitButton.triggered.connect(self.quit)


        self.setContextMenu(mainMenu)


    def enable_login_etc(self):
        self.logInButton.setEnabled(True)
        self.msgButton.setEnabled(True)

    def toggle_login_logout_button(self):
        self.logInButton.setEnabled(False)
        self.logoutButton.setEnabled(True)

    def create_uuid(self, UUID_string):
        return uuid.uuid3(uuid.NAMESPACE_DNS, UUID_string)

    def change_icon_on_login(self):
        self.setIcon(QIcon('icons/icon-placeholder_128x128_green.png'))

    def present_login_form(self):
        self.login_form = LoginForm(self)
        self.login_form.show()

    def present_timestamp_form(self):
        url = self.createURL('/last_activity_duration/')
        response = self.http_client.get(url)
        self.timestamp_form = TimestampForm(self, response.text)
        self.timestamp_form.show()

    def show_token(self):
        """Placeholder function"""

        try:
            self.showMessage('Token',
                             self.token,
                             QSystemTrayIcon.Information,
                             3000)
        except:
            self.showMessage('Token',
                             'No token received',
                             QSystemTrayIcon.Information,
                             3000)
    def test_sockets(self):
        """Placeholder function"""

        self.showMessage('Testing',
                         'Pending implementation',
                         QSystemTrayIcon.Information,
                         3000)

    #How to logout currently logged in user through get request
    def logout(self):
        url = self.createURL('/user_logout/')
        response = self.http_client.get(url)
        if response.status_code == 200:
            print("Response from view >>>>>>>", response.text)

          **WHAT TO DO HERE?**  


    def quit(self):
        """Exit program in a clean way."""
        if os.path.isfile('pid'):
            os.remove('pid') 
            print ("Deleting pid file")
        print ("Exiting")
        sys.exit(0)

服务器应用 - urls.py

url(r'^user_logout/$', views.user_logout, name='user_logout'),

服务器应用 - views.py

@verified_email_required  
def user_logout(request):
    print(request.user)
    logout(request)
    return HttpResponse('User is logged out')

我的login.py。这就是我用户登录的方式。

from PyQt5 import QtCore
from PyQt5.QtWidgets import QDesktopWidget
from PyQt5.QtWidgets import QFormLayout, QHBoxLayout, QMessageBox
from PyQt5.QtWidgets import QLabel, QLineEdit, QPushButton
from PyQt5.QtWidgets import QWidget



#from utility import encrypt_data

class LoginForm(QWidget):

def __init__(self, parent_tray):
    super(LoginForm, self).__init__()

    # keeping reference to parent
    self.parent_tray = parent_tray

    # define fixed size
    self.fixedWidth = 250
    self.fixedHeight = 100

    # no min, max, close button
    self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint |
                        QtCore.Qt.CustomizeWindowHint |
                        QtCore.Qt.WindowTitleHint)

    self.create_ui()
    self.move_to_primary_center()
    self.setWindowTitle("Log in")


def create_ui(self):
    """Create user interface for login popup window"""

    emailLabel = QLabel("Email:")
    passwordLabel = QLabel("Password:")
    self.email = QLineEdit()
    self.password = QLineEdit()
    print (self.email.whatsThis())

    self.email.setPlaceholderText("Enter your email")
    self.password.setPlaceholderText("Enter your password")



    # Show asterisk in input instead of password chars
    self.password.setEchoMode(QLineEdit.Password)

    submitButton = QPushButton("Submit")

    # Usign lambda because Qt doesn't allow for arguments to by passed to slots
    # And we want to keep email and password as a private variables so we
    # don't want to make them direct members of Class and call them with self
    # directly inside self.submit() function
    submitButton.clicked.connect(lambda: self.submit(self.parent_tray,
                                                     self.email.text(),
                                                     self.password.text()))

    # Enter pressed inside password line edit
    self.password.returnPressed.connect(lambda: self.submit(self.parent_tray,
                                                       self.email.text(),
                                                       self.password.text()))

    self.email.returnPressed.connect(self.password.setFocus)

    cancelButton = QPushButton("Cancel")
    cancelButton.clicked.connect(self.cancel)

    #Design a form layout
    formBox = QFormLayout()
    formBox.addRow(emailLabel, self.email)
    formBox.addRow(passwordLabel, self.password)

    # sign up label / link
    signUpLabel = QLabel()
    signUpLabel.setText('<a href="http://localhost:8000/sign-up/">Sign Up</a>')
    signUpLabel.setOpenExternalLinks(True)
    signUpLabel.show()

    # recover password link
    recoverLabel = QLabel()
    recoverLabel.setText('<a href="http://localhost:8000/recover-password/">Forgot your password?</a>')
    recoverLabel.setOpenExternalLinks(True)
    recoverLabel.show()

    # build sign up row
    signUpRow = QHBoxLayout()
    signUpRow.addWidget(signUpLabel)
    signUpRow.addWidget(recoverLabel)

    #add sign up row
    formBox.addRow(signUpRow)


    buttonRow = QHBoxLayout()
    buttonRow.addWidget(submitButton)
    buttonRow.addWidget(cancelButton)

    # add button row
    formBox.addRow(buttonRow)

    # Set layout for the Login Form (self)
    self.setLayout(formBox)

    try:
        last_user = open ('last_user', 'r').read()
        self.email.setText(last_user)
        self.password.setFocus()
    except:
        pass

    # Disable resize
    self.setFixedSize(self.fixedWidth, self.fixedHeight)

def move_to_primary_center(self):
    """Reposition window to center of primary screen"""

    desktop = QDesktopWidget()
    primaryScreenIndex = desktop.primaryScreen()
    rectScreenPrimarty = desktop.screenGeometry(primaryScreenIndex)

    # center in the middle of screen, considering window's own size
    self.move(rectScreenPrimarty.center().x() - self.fixedWidth/2,
              rectScreenPrimarty.center().y() - self.fixedHeight/2)


def submit(self, parentTray, email, password):
    """Send data to server."""

    if not email or not password:

        msgBox = QMessageBox()
        info_text = []
        if not email:
            info_text.append('Email cannot be empty!')
        if not password:
            info_text.append('Password cannot be empty!')

        joined_info_text = '\n \n'.join(info_text)

        msgBox.setInformativeText(joined_info_text)
        msgBox.setIcon(QMessageBox.Information)
        msgBox.setWindowTitle("Oops!")

        msgBox.setStandardButtons(QMessageBox.Ok)
        msgBox.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        msgBox.exec()

    else:
        url = parentTray.createURL('/accounts/login/')
        print('Trying to authenticate on', url)
        try:
            response = self.parent_tray.http_client.post(
                url,
                headers = {
                    'X-CSRFToken':self.parent_tray.http_client.cookies.get('csrftoken'),
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                data={
                    'login' : email,
                    'password' : password,
                    'client_public_key' : self.parent_tray.client_rsa.publickey().exportKey(),
                    'uuid' : parentTray.uuid
                }
            )
            print(parentTray.uuid)
        except Exception as e:
            print ('No response, server may be down')

        if response.status_code != 200:
            msgBox = QMessageBox()
            msgBox.setInformativeText('Invalid email and/or password')
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Oops!")

            msgBox.setStandardButtons(QMessageBox.Ok)
            msgBox.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
            msgBox.exec()
            self.show()
            return False

        else: # if user logged in successfully
            parentTray.change_icon_on_login()
            parentTray.verify_initial_data()
            with open ('last_user' ,'w') as f:
                f.write(email) 
            self.parent_tray.showMessage('Success',
                 'You are logged in as {}'.format(email),
                 parentTray.Information,
                 3000)
            self.close()



def cancel(self):
    """Close password input"""
    self.close()

1 个答案:

答案 0 :(得分:0)

这是一个意见问题,它取决于您希望应用程序架构(前端和后端)的运行方式。

如果我按照django的方式做一些事情作为桌面应用程序的后端,我会把它写成API并使用JWOT身份验证。这样我的身份验证状态就是使用令牌,我可以设置过期限制,每个请求都需要此令牌作为身份验证的形式。

我没有看到表单演示的登录方法,您究竟是如何登录用户并跟踪该状态的?如果您回答这个问题,那么回答退出问题会更容易。

对不起答案,根据StackOverflow的精彩规则,无法发表评论。