diff --git a/server/apps/exam/views.py b/server/apps/exam/views.py index 4e89fa1..ceb0e89 100644 --- a/server/apps/exam/views.py +++ b/server/apps/exam/views.py @@ -27,6 +27,8 @@ from apps.exam.parse_word import interpret_text import os import shutil from django.db.models import Q +from django_redis import get_redis_connection +import uuid # Create your views here. EXCEL_PATH = os.path.join(settings.BASE_DIR, "media/default/question.xlsx") @@ -524,6 +526,7 @@ class ExamViewSet(CreateUpdateCustomMixin, ModelViewSet): now = timezone.now() if now < exam.open_time or now > exam.close_time: raise ParseError('不在考试时间范围') + ExamRecord.objects.filter(exam=exam, create_by=request.user, is_submited=False).delete() tests = ExamRecord.objects.filter( exam=exam, create_by=request.user) chance_used = tests.count() @@ -685,6 +688,9 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G courese_ids = [i.id for i in course] current_date = now_data.strftime('%Y-%m-%d') cer_number = now_data.strftime('%Y%m%d') + # redis 连接并获取锁 + redis_conn = get_redis_connection("redis") + identifier = acquire_lock(redis_conn, 'certificate', 10) # 查询证明编号创建时间为最后一个 cer = Certificate.objects.latest('证书编号') if cer: @@ -706,10 +712,45 @@ class ExamRecordViewSet(ListModelMixin, DestroyModelMixin, RetrieveModelMixin, G serializer = CertificateSerializer(data=data_dict) serializer.is_valid(raise_exception=True) serializer.save() + # 释放锁 + if identifier: + release_lock(redis_conn, 'certificate', identifier) + else: + print("没有找到锁") er.took = (now - er.create_time).total_seconds() er.end_time = now er.belong_dept=request.user.dept er.is_submited = True er.save() - return Response(ExamRecordListSerializer(instance=er).data) \ No newline at end of file + return Response(ExamRecordListSerializer(instance=er).data) + + +def acquire_lock(redis_conn, lock_name, ttl): + identifier = str(uuid.uuid4()) + lock = redis_conn.set(lock_name, identifier, nx=True, ex=ttl) + return identifier if lock else None + + +import redis +def release_lock(redis_conn, lock_name, identifier): + with redis_conn.pipeline() as pipe: + try: + while True: + try: + pipe.watch(lock_name) + # 使用 multi/exec 模式来确保原子性 + if pipe.get(lock_name) == identifier: + pipe.multi() + pipe.delete(lock_name) + pipe.execute() + return True + # 如果锁已经被修改,取消监视 + pipe.unwatch() + return False + except redis.exceptions.WatchError: + # 如果在监视期间锁被修改,重试 + continue + except redis.exceptions.RedisError as e: + print(f"Error releasing lock: {e}") + return False \ No newline at end of file diff --git a/server/server/settings.py b/server/server/settings.py index b6998d2..97bed41 100644 --- a/server/server/settings.py +++ b/server/server/settings.py @@ -196,14 +196,14 @@ AUTHENTICATION_BACKENDS = ( # 缓存配置 CACHES = { - # "default": { - # "BACKEND": "django_redis.cache.RedisCache", - # "LOCATION": "redis://127.0.0.1:6379/9", - # "OPTIONS": { - # "CLIENT_CLASS": "django_redis.client.DefaultClient", - # # "PICKLE_VERSION": -1 - # } - # } + "redis": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "redis://127.0.0.1:6379/1", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + # "PICKLE_VERSION": -1 + } + }, 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', 'LOCATION': os.path.join(BASE_DIR, 'temp'), diff --git a/ssl/testsearch.ctc.ac.cn.key b/ssl/testsearch.ctc.ac.cn.key index cc65336..e2722d7 100644 --- a/ssl/testsearch.ctc.ac.cn.key +++ b/ssl/testsearch.ctc.ac.cn.key @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/ssl/testsearch.ctc.ac.cn.pem b/ssl/testsearch.ctc.ac.cn.pem index 0a375f2..6cdcdb7 100644 --- a/ssl/testsearch.ctc.ac.cn.pem +++ b/ssl/testsearch.ctc.ac.cn.pem @@ -1,36 +1,36 @@ -----BEGIN CERTIFICATE----- -MIIF+DCCBGCgAwIBAgIQexRxjj+11hqqdmSmDPdOlzANBgkqhkiG9w0BAQwFADBZ -MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg -SW5jLjEjMCEGA1UEAxMaVHJ1c3RBc2lhIFJTQSBEViBUTFMgQ0EgRzIwHhcNMjQw -NDI4MDAwMDAwWhcNMjQwNzI3MjM1OTU5WjAfMR0wGwYDVQQDExR0ZXN0c2VhcmNo -LmN0Yy5hYy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK7PhH8d -qp3Hgpff2f0nc08XCLGrDdPpoQqCDSVfMKwQHosh1A25pvgOGhFWIuFt1NosO+iC -i17g5QYWf3ExyLlBs9mMKXhMGT8tSX0XhVs/QH4+pgZ4t9D2YyFzQr7gq7YqqKrq -EEnwNY+B60l6y0A/hoUu/BvO3Uy9YLp0i4jqxCPTgOXZp7lpqLYKHgSLffFN9caM -XE3GFgqDPEZH6nJSY4IfUoXvz6FbwTxo7wf53WDcBTOst4GZpew3RKR7Ng66LSbm -5YNqe5eAdEtKx2kOQdw607SOrZ80yKYv4the4iJwgm7A2CE2W9HrOhtTgmPquflC -cjn3dWoYwHaUB2UCAwEAAaOCAnQwggJwMB8GA1UdIwQYMBaAFF86fBEQfgxncWHc -i6O1AANn9VccMB0GA1UdDgQWBBTV7evfTKgBsYGqCBrDMmQaKGNOfzAOBgNVHQ8B -Af8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB -BQUHAwIwSQYDVR0gBEIwQDA0BgsrBgEEAbIxAQICMTAlMCMGCCsGAQUFBwIBFhdo -dHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwBAgEwfQYIKwYBBQUHAQEEcTBv -MEIGCCsGAQUFBzAChjZodHRwOi8vY3J0LnRydXN0LXByb3ZpZGVyLmNuL1RydXN0 -QXNpYVJTQURWVExTQ0FHMi5jcnQwKQYIKwYBBQUHMAGGHWh0dHA6Ly9vY3NwLnRy -dXN0LXByb3ZpZGVyLmNuMIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDwAHYAdv+IPwq2 -+5VRwmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQAAAGPIp9pcAAABAMARzBFAiAPFwsT -MTHT+pW/FPjFDO6DsZ7nYBM0IUK7g15j5EK9bgIhAIeT4eBXZdQTbf8kuVz9EWbI -rFi4HCc1N2rha6gMMT4eAHYAPxdLT9ciR1iUHWUchL4NEu2QN38fhWrrwb8ohez4 -ZG4AAAGPIp9pGgAABAMARzBFAiEA4BiPF2rZW5q8Tm9MzN5p+Kw1JSly5aUxSyW/ -lq6A75ACIAaQ7Elxeh1jdJ+95sgWCvzPKzdxFNf6GeN2D/J+8eCdMB8GA1UdEQQY -MBaCFHRlc3RzZWFyY2guY3RjLmFjLmNuMA0GCSqGSIb3DQEBDAUAA4IBgQCWRf25 -QmMBQ6PnR2d7ITksepeHFWWp1iqF1sUz4XGvEqXvPIideGHXbSV+2mwspFtf9aEd -Xy8R7RbbCbs+RfQ/nNMHECKChwdnDUOs/9v2yLE2ZPaJtO+P2/FenOBVfxDMjhd6 -yrFXwojUM3PI1gJz+a5LRq8Jqun8DcBuYGSQNS1mM32pwKEpoxmvMe1WYB5ZtYc7 -fbUq+TD0UgAgyiFbXvnRK1fgZn2v2ue2Cm9JsDsW0ouj9uhifLP0VlfUvUHvYEOh -0C2lyIfOyvgz2u5YJmi7uJrM8cssDv6roOyCJLTnH8iwbqskMlaIEDt2b3Nu2cLZ -x6iN8sgx4W+UYzMl0jWZ6Vgt5F9wuhPnMOPozxNWwYO7JlrTdLGF0JAFLS5kR3vD -HPtRrjwV6Wqlrq4pCPq+T6jmDgQNah2A2vTbuTelJkVYppYE2Pi6l+lfmGDGACzf -zW3IJ+kXW8gw8zxlnU0fC5YlY8ItxBhmVkOFqWG78Tuw9QjWDxhS6fJuisE= +MIIF+jCCBGKgAwIBAgIRAIa1G6aR/Fioa94iEdzo93AwDQYJKoZIhvcNAQEMBQAw +WTELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs +IEluYy4xIzAhBgNVBAMTGlRydXN0QXNpYSBSU0EgRFYgVExTIENBIEcyMB4XDTI0 +MDcyNTAwMDAwMFoXDTI0MTAyMzIzNTk1OVowHzEdMBsGA1UEAxMUdGVzdHNlYXJj +aC5jdGMuYWMuY24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcn5Lx +Rl1ea9Vla6HXZhmECotpR6vVdIQOXr+clRzzvQP9WehjNi790GB2uItGTf59vhSW +L+O7YBw8uDoTWSk3Tx1eYz3kuC4wCCEAouPA538IyaDxzlKEu7p0e9vyldbK37Cb +v6DvhDu6dbDRU6E0bm+M+M/2k2umIWHkHBLKJHoMWS0usdzRt9BsacPwhGb9zasV +cqae3BAMhkW0sKakYrNRvpRRyenQFa4CpnTz35Xbiqgp/m8NcZ+vj/7bbnbYB2xv +RECNWME+N9shEhvp0t8Iks5Zx7JAH2t6pindzr9kYnExOZvvj1eILTo+JJUKZudI +nMo8lINRACa4CTvNAgMBAAGjggJ1MIICcTAfBgNVHSMEGDAWgBRfOnwREH4MZ3Fh +3IujtQADZ/VXHDAdBgNVHQ4EFgQU/YrAK+ohcvVU/+CvttRblIR/+wkwDgYDVR0P +AQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMEkGA1UdIARCMEAwNAYLKwYBBAGyMQECAjEwJTAjBggrBgEFBQcCARYX +aHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQIBMH0GCCsGAQUFBwEBBHEw +bzBCBggrBgEFBQcwAoY2aHR0cDovL2NydC50cnVzdC1wcm92aWRlci5jbi9UcnVz +dEFzaWFSU0FEVlRMU0NBRzIuY3J0MCkGCCsGAQUFBzABhh1odHRwOi8vb2NzcC50 +cnVzdC1wcm92aWRlci5jbjCCAQUGCisGAQQB1nkCBAIEgfYEgfMA8QB2AHb/iD8K +tvuVUcJhzPWHujS0pM27KdxoQgqf5mdMWjp0AAABkOrIbCgAAAQDAEcwRQIhAKMh +WiCNFtHEtcomCMpuZNT4biC6PC3tssg/q9xwlkCeAiBdywwLj6WslkEhABd/ryKi ++vgLV9p8N/yyoLaJijuJFwB3AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs ++GRuAAABkOrIbAgAAAQDAEgwRgIhANI2dmapoZ+UNug9z2k4f7nYgo/ivoWeSUTB +qBz4HKGMAiEAy8XRkgBuLCFA5o5C2y8kV2cxSRH7/SFRis/8pD9KFCYwHwYDVR0R +BBgwFoIUdGVzdHNlYXJjaC5jdGMuYWMuY24wDQYJKoZIhvcNAQEMBQADggGBAFWX +4/J0bJftykwPa7RwkSWqID39bx4WUJNBDbaDtPod49dd9xSVvN4ZPCEdAOr7OL8l +Yb+YVdSraKaZy+G/8gY8HxRjRAisEXOeyVmhcMl0P4vOf8SfBw8FQq4J+gLidV7+ +gW2vnCFv9F5alPN44UXWUOevN7EFsv+XWW0Jbnuat5pvH4r38z/pnFdKWp1fiMOS +T/AyqWTtS2fzvbc6RjpuwPdkR4MyFI0KfKDWuEhUma9aJRhXKLVG1iJOqzuVpE7l +mYXq4yla3SlY3kfTR9rT+2KKG4TYxJCHkimx9rkBD5P/RGAAwH9IJs2UkCGiA+3i +VcNeUsrMsOQ9qFk7vtDgBCN+mx1pt6/gWGZKsyjZtmqzyVoCp8dv0AE/2skpYSSQ +1QXMJIK/uyvNRgPfQqbXaxhZq6loukIydIIJEAXit8SBnFaKvYXluiywModpYXBP +85rtLnuVjgg615uSEkaI7okU74RgN0IFI7q2sOP1j5YeSX0srQTwV5Aw4nhrWA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFBzCCA++gAwIBAgIRALIM7VUuMaC/NDp1KHQ76aswDQYJKoZIhvcNAQELBQAw