from django.shortcuts import render from django.http import Http404 import redis import uuid from redis_app.utils.index import create_index # This model only helps us the development part to set rules on objects (we do not use the django model to save objects in it) from .models import Person DEFAULT_EXPIRE_TIME = 120 EXPIRE_REFRESH_TIME = 60 COURSE_CHANNEL = "course" cancel = True personLoggedIn = "" redis_connection = redis.Redis(host='localhost', port=6379, decode_responses=True) pub_sub = redis_connection.pubsub() create_index(redis_connection=redis_connection) def getPersonId(person_name, person_role): query = f"@name:{person_name} @role:{person_role}" results = redis_connection.execute_command('FT.SEARCH', 'idx:persons', query) if results[0] > 0: person_key = results[1] return person_key return False def getCourseId2(course_title, course_teacher): query = f"@title:{course_title} @teacher:{course_teacher}" results = redis_connection.execute_command('FT.SEARCH', 'idx:courses', query) if results[0] > 0: course_key = results[1] return course_key return False def getCourseId(course): return getCourseId2(course.get("title"), course.get("teacher")) def home(request, person=''): global cancel cancel = True return render(request, 'home.html', {'person': person}) def details(request, course_id): global redis_connection global cancel global personLoggedIn cancel = True course = redis_connection.hgetall(f"course:{course_id}") if not course: raise Http404("Course does not exist") course_id = getCourseId2(course['title'], course['teacher']) if course_id == False: raise Http404("Course does not exist") course['id'] = course_id.split(":")[1] return render(request, 'details.html', {'course': course, 'person': personLoggedIn}) # Handle error messages. def register(request): global personLoggedIn global redis_connection global cancel cancel = True if request.method == 'POST': person_name = request.POST.get('name') person_role = request.POST.get('role') query = f"@name:{person_name} @role:{person_role}" results = redis_connection.execute_command('FT.SEARCH', 'idx:persons', query) # First element = number of results if results[0] > 0: return render(request, 'register.html', {'person': Person(name="", role=""), "error_message": "This user already exists!"}) person_key = f"person:{uuid.uuid4()}" redis_connection.hset(person_key, mapping={ 'name': person_name, 'role': person_role }) personLoggedIn = redis_connection.hgetall(person_key) return home(request, personLoggedIn) return render(request, 'register.html', {'person': Person(name="", role=""), "error_message": "The form has been wrongly filled!"}) def login(request): global personLoggedIn global redis_connection global cancel cancel = True if request.method == 'POST': person_name = request.POST.get('name') person_role = request.POST.get('role') query = f"@name:{person_name} @role:{person_role}" results = redis_connection.execute_command('FT.SEARCH', 'idx:persons', query) if results[0] > 0: person_key = results[1] personLoggedIn = redis_connection.hgetall(person_key) return home(request, personLoggedIn) return render(request, 'login.html', {'person': Person(name="", role=""), "error_message": "No user found!"}) return login_form(request) def register_form(request): global cancel cancel = True return render(request, 'register.html', {'person': Person(name="", role="")}) def login_form(request): global cancel cancel = True return render(request, 'login.html', {'person': Person(name="", role="")}) def logout(request): global personLoggedIn global cancel cancel = True personLoggedIn = "" return render(request, 'login.html', {'person': Person(name="", role="")}) def courses(request): global personLoggedIn global cancel cancel = True if personLoggedIn == "": return render(request, 'login.html', {'person': Person(name="", role=""), "error_message": "You must login!"}) person_id = getPersonId(personLoggedIn["name"], personLoggedIn["role"]).split(":")[1] course_keys = redis_connection.keys(f"course:*") courses = [] for key in course_keys: course_data = redis_connection.hgetall(key) if personLoggedIn['role'] == "Student": if person_id in course_data.get("students", "").split(","): course_id = getCourseId2(course_data['title'], course_data['teacher']) if course_id == False: continue course_data['id'] = course_id.split(":")[1] courses.append(course_data) else: teacher_id = course_data["teacher"] if teacher_id == person_id: course_id = getCourseId2(course_data['title'], course_data['teacher']) if course_id == False: continue course_data['id'] = course_id.split(":")[1] courses.append(course_data) return render(request, 'courses.html', {'person': personLoggedIn, 'courses': courses}) def change_profile(request): global personLoggedIn global cancel cancel = True if personLoggedIn == '': return render(request, 'login.html', {'person': Person(name="", role=""), "error_message": "You must login!"}) if request.method == 'POST': person_name = request.POST.get('name') person_role = request.POST.get('role') person_id = getPersonId(personLoggedIn["name"], personLoggedIn["role"]) if not person_id: return render(request, 'profile.html', {'person': personLoggedIn, "error_message": "Internal error: No user found!"}) redis_connection.hmset(person_id, mapping={"name": person_name, "role": person_role}) personLoggedIn["name"] = person_name personLoggedIn["role"] = person_role return render(request, 'profile.html', {'person': personLoggedIn}) return login_form(request) def profile(request): global personLoggedIn global cancel cancel = True if personLoggedIn == '': return render(request, 'login.html', {'person': Person(name="", role=""), "error_message": "You must login!"}) return render(request, 'profile.html', {'person': personLoggedIn}) def delete_course(course_id): course = redis_connection.hgetall(f"course:{course_id}") if not course: return False redis_connection.delete(f"course:{course_id}") return True def delete_course_view(request, course_id): global personLoggedIn res = delete_course(course_id) if not res: return courses(request) return courses(request) def create_course(course_title, course_summary, course_level, course_places, course_teacher): course_id = uuid.uuid4() redis_connection.hset(f"course:{course_id}", mapping={ "title": course_title, "summary": course_summary, "level": course_level, "places": course_places, "teacher": course_teacher }) redis_connection.expire(f"course:{course_id}", DEFAULT_EXPIRE_TIME) def create_course_view(request): global personLoggedIn return render(request, 'create.html', {'person': personLoggedIn}) def create_course_form(request): global personLoggedIn global redis_connection global cancel cancel = True if personLoggedIn == '': return render(request, 'login.html', {'person': Person(name="", role=""), "error_message": "You must login!"}) if request.method == 'POST': course_title = request.POST.get('title') course_summary = request.POST.get('summary') course_level = request.POST.get('level') course_places = request.POST.get('places') course_teacher = getPersonId(personLoggedIn.get('name'), personLoggedIn.get('role')).split(":")[1] course_key = f"course:{uuid.uuid4()}" redis_connection.hset(course_key, mapping={ 'title': course_title, 'summary': course_summary, 'level': course_level, 'places': course_places, 'teacher': course_teacher }) return courses(request) return render(request, 'create.html', {'person': personLoggedIn, "error_message": "The form has been wrongly filled!"}) def course_register(course_id, person_id): course = redis_connection.hgetall(f"course:{course_id}") person = redis_connection.hgetall(f"person:{person_id}") if not course or not person: return False students = course.get('students', '') if person_id in students.split(','): return True if students: new_students = person_id else: new_students = students + "," + person_id redis_connection.hset(f"course:{course_id}", "students", new_students) return True def course_unregister(course_id, person_id): course = redis_connection.hgetall(f"course:{course_id}") person = redis_connection.hgetall(f"person:{person_id}") if not course or not person: return False students = course.get('students', '') if person_id not in students.split(','): return True students_list = students.split(",") if len(students_list) == 1: new_students = "" else: new_students = ",".join([student for student in students_list if student != person_id]) redis_connection.hset(f"course:{course_id}", "students", new_students) return True def refresh_expire(course_id): course = redis_connection.hgetall(f"course:{course_id}") if not course: return False ttl = redis_connection.ttl(f"course:{course_id}") if ttl <= 0: return False redis_connection.expire(f"course:{course_id}", ttl + EXPIRE_REFRESH_TIME) return True def publish(course): pub_sub.publish(COURSE_CHANNEL + ":" + getCourseId(course), str(course)) # Courses is a list of coursee id to subscribe to def subscribe(courses_id): global cancel cancel = False pub_sub.psubscribe(*courses_id) for message in pub_sub.listen(): if cancel: break if message["type"] != 'pmessage': continue send_new_course_notification(message) def send_new_course_notification(message): print(message) # Every id is only the number, not the course:number or person:number