apache Django 3.2 post_保存信号调用所有模型示例,即使代码中使用了1个示例进行保存

bmvo0sr5  于 2023-01-09  发布在  Apache
关注(0)|答案(1)|浏览(106)

bounty已结束。此问题的答案可获得+100的信誉奖励。奖励宽限期将在21小时后结束。user956424正在寻找来自信誉良好来源的答案:它在Apache后面运行,并为任何邮箱示例填充相同的密码,按下保存按钮,最终在所有5个密码字段中存在该示例。

当我们点击django模型管理中的保存按钮时,是否会为所有邮箱模型示例调用post_保存信号?post_save信号是否会在Apache服务器中持续工作?当它在Apache后面执行时,当我们刷新页面时,它会再次在下一个密码列中保存与前一个密码列相同的密码。我需要检查密码历史记录,以确保5个密码不重复。post_save代码:

def check_oldest_password_instance(mbox):
    passwd_list =  []
    oldest_password = None
    oldest_password_datetime = datetime.now()
    pfield = '1'
    n = 0
    mphistory = Phistory.objects.filter(mbox=mbox)
    if mphistory:
        print('======phistory exists====', mphistory)
        for p in mphistory:
            if p.password1:
                passwd_list.append(p.password1)
                oldest_password_datetime = p.datetime1
                oldest_password = p.password1
                pfield = '1'
            if p.password2:
                passwd_list.append(p.password2)
                if oldest_password_datetime > p.datetime2:
                    oldest_password_datetime = p.datetime2
                    oldest_password = p.password2
                    pfield = '2'
            if p.password3:
                passwd_list.append(p.password3)
                if oldest_password_datetime > p.datetime3:
                    oldest_password_datetime = p.datetime3
                    oldest_password = p.password3
                    pfield = '3'
            if p.password4:
                passwd_list.append(p.password4)
                if oldest_password_datetime > p.datetime4:
                    oldest_password_datetime = p.datetime4
                    oldest_password = p.password4
                    pfield = '4'
            if p.password5:
                passwd_list.append(p.password5)
                if oldest_password_datetime > p.datetime5:
                    oldest_password_datetime = p.datetime5
                    oldest_password = p.password5
                    pfield = '5'
        print(len(passwd_list),pfield,'passwd_list_len,pfield_oldest')
        n = len(passwd_list)
        # For new mailbox, check if all 5 values are populated 
        # if n == 0:
        #     pfield = '1'
        if n == 1:
            pfield = '2'
        if n == 2:
            pfield = '3'
        if n == 3:
            pfield = '4'
        if n == 4:
            pfield = '5'
        print(pfield,n, 'pfield-n------------------')
    else:
        oldest_password = None
        n = 0
        pfield = '1'

    return (pfield, passwd_list)

def mbox_post_save(sender, instance, created, **kwargs):
    mphistory = None
    new_phistory = None
    mphistory = None
    print('post save callllll')
    if created:
        # Store the hashed password in Phistory table
        #----------------
        new_phistory = Phistory()
        new_phistory.mbox = instance
        new_phistory.password1 = instance.mpassword
        new_phistory.datetime1 = datetime.now()
        new_phistory.save()
        #----------------
    else:
        print('# edit mbox post_save')

        # Store the hashed password in Phistory table
        #----------------
        try:
            mphistory = Phistory.objects.get(mbox=instance)
            print(mphistory,'mppppp=======================')
        except Exception as e:
            print(e)
        if mphistory:
            print('PHISTORY--------')
            (oldest_pfield, passwd_list) = check_oldest_password_instance(instance)
            if oldest_pfield == '1':
                mphistory.password1 = instance.mpassword
                mphistory.datetime1 = datetime.now()
            elif oldest_pfield == '2':
                mphistory.password2 = instance.mpassword
                mphistory.datetime2 = datetime.now()
            elif oldest_pfield == '3':
                mphistory.password3 = instance.mpassword
                mphistory.datetime3 = datetime.now()
            elif oldest_pfield == '4':
                mphistory.password4 = instance.mpassword
                mphistory.datetime4 = datetime.now()
            elif oldest_pfield == '5':
                mphistory.password5 = instance.mpassword
                mphistory.datetime5 = datetime.now()
            mphistory.save()
        else:
            if not mphistory:
                print('# Add new phistory object 1st time for existing mbox')
                new_phistory = Phistory()
                new_phistory.mbox = instance
                new_phistory.password1 = instance.mpassword
                new_phistory.datetime1 = datetime.now()
                new_phistory.save()
        #----------------

    return

post_保存信号的连接方式:

post_save.connect(mbox_post_save, sender=Mbox)
kupeojn6

kupeojn61#

要回答您的问题:
如果您从/admin部分保存对象,Post_save仍将生效
它应该监听特定对象的所有保存--它不应该为该类型的每个对象启动post_save例程。如果你遇到这种情况,很可能是其他地方出了问题,但我在这里提供的代码中看不到。
检查以前的密码是否存在相当简单。但是我认为您将所有这些作为post_save信号是错误的。如果您执行post_save操作,您将 * 已经 * 保存邮箱密码,如果密码历史检查失败,您将需要撤消更改。
最好将其放在表单的clean()函数中,这样,如果有历史记录匹配,就可以出错。
我会这样做:
forms.py

#first some support functions

def get_password_history(mbox):
     #Is there an existing Phistory?
     try:
         mphistory = Phistory.objects.get(mbox=mbox)
     except Phistory.DoesNotExist
         return False
     return mphistory    

def is_password_used(mphistory, password):
    #look for the password in the existing records
    password_list = [
                mphistory.password1, 
                mphistory.password2, 
                mphistory.password3, 
                mphistory.password4, 
                mphistory.password5, 
            ]
    if password in password_list:
         return True
    return False

def update_password_history(mphistory, password):
    #I haven't bothered with datetime here as the oldest is always the highest,
    #but if you need it you can add lines for that field to do a similar swap.
    mphistory.password5  = mphistory.password4 
    mphistory.password4  = mphistory.password3 
    mphistory.password3  = mphistory.password2
    mphistory.password2  = mphistory.password1 
    mphistory.password1  = password
    mphistory.save()

then in your form.py clean method

def clean(self):
    cleaned_data = super().clean()
    history = get_password_history(self)
    if history:
        previous_password_exists = is_password_used(history, cleaned_data.get('mpassword')
        if previous_password_exists:
            raise forms.ValidationError(
                "The password has been used in the last five changes"
            )
        else:
            #the below could also be done in your view after form.is_valid for clarity
            update_password_history(history, cleaned_data.get('mpassword'))

现在您可以保留post_save,以便在创建邮箱时创建新的密码历史记录。

def mbox_post_save(sender, instance, created, **kwargs):
    print('post save phistory creation')
    if created:
        # Store the hashed password in Phistory table
        #----------------
        new_phistory = Phistory()
        new_phistory.mbox = instance
        new_phistory.password1 = instance.mpassword
        new_phistory.datetime1 = datetime.now()
        new_phistory.save()
        #----------------

    return

相关问题