Skip to content

Commit

Permalink
create user filter set
Browse files Browse the repository at this point in the history
  • Loading branch information
SKairinos committed Oct 13, 2023
1 parent f11c555 commit 2108c96
Show file tree
Hide file tree
Showing 17 changed files with 465 additions and 291 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name = "pypi"
[packages]
django = "==3.2.20"
djangorestframework = "==3.13.1"
django-filter = "==23.2"
django-countries = "==7.3.1"
django-two-factor-auth = "==1.13.2"
django-cors-headers = "==4.1.0"
Expand Down
343 changes: 182 additions & 161 deletions Pipfile.lock

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions codeforlife/pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from rest_framework.pagination import (
LimitOffsetPagination as _LimitOffsetPagination,
)
from rest_framework.response import Response


class LimitOffsetPagination(_LimitOffsetPagination):
default_limit = 50
max_limit = 500

def get_paginated_response(self, data):
return Response(
{
"count": self.count,
"offset": self.offset,
"limit": self.limit,
"max_limit": self.max_limit,
"results": data,
}
)
13 changes: 13 additions & 0 deletions codeforlife/settings/third_party.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,16 @@
CORS_ALLOW_ALL_ORIGINS = DEBUG
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = ["https://www.codeforlife.education"]

# REST framework
# https://www.django-rest-framework.org/api-guide/settings/#settings

REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend"
],
"DEFAULT_PAGINATION_CLASS": "codeforlife.pagination.LimitOffsetPagination",
}
1 change: 1 addition & 0 deletions codeforlife/user/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .user import UserFilter
13 changes: 13 additions & 0 deletions codeforlife/user/filters/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django_filters import rest_framework as filters

from ..models import User


class UserFilter(filters.FilterSet):
student__klass = filters.CharFilter(
"new_student__class_field__access_code", "exact"
)

class Meta:
model = User
fields = ["student__klass"]
4 changes: 2 additions & 2 deletions codeforlife/user/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
# # from .other import *
# from .school import School
# from .session import UserSession
# from .student import Student
# from .teacher_invitation import SchoolTeacherInvitation
# from .teacher import Teacher
from .auth_factor import AuthFactor
from .otp_bypass_token import OtpBypassToken
from .session import Session
from .session_auth_factor import SessionAuthFactor
from .student import Student
from .teacher import Teacher
from .user import User
144 changes: 73 additions & 71 deletions codeforlife/user/models/student.py
Original file line number Diff line number Diff line change
@@ -1,71 +1,73 @@
from uuid import uuid4

from django.db import models

from .user import User
from .classroom import Class


class StudentModelManager(models.Manager):
def get_random_username(self):
while True:
random_username = uuid4().hex[:30] # generate a random username
if not User.objects.filter(username=random_username).exists():
return random_username

def schoolFactory(self, klass, name, password, login_id=None):
user = User.objects.create_user(
username=self.get_random_username(),
password=password,
first_name=name,
)

return Student.objects.create(
class_field=klass, user=user, login_id=login_id
)

def independentStudentFactory(self, name, email, password):
user = User.objects.create_user(
username=email, email=email, password=password, first_name=name
)

return Student.objects.create(user=user)


class Student(models.Model):
class_field = models.ForeignKey(
Class,
related_name="students",
null=True,
blank=True,
on_delete=models.CASCADE,
)
# hashed uuid used for the unique direct login url
login_id = models.CharField(max_length=64, null=True)
user = models.OneToOneField(
User,
related_name="student",
null=True,
blank=True,
on_delete=models.CASCADE,
)
pending_class_request = models.ForeignKey(
Class,
related_name="class_request",
null=True,
blank=True,
on_delete=models.SET_NULL,
)
blocked_time = models.DateTimeField(null=True, blank=True)

objects = StudentModelManager()

def is_independent(self):
return not self.class_field

def __str__(self):
return f"{self.user.first_name} {self.user.last_name}"


def stripStudentName(name):
return re.sub("[ \t]+", " ", name.strip())
# from uuid import uuid4

# from django.db import models

# from .user import User
# from .classroom import Class


# class StudentModelManager(models.Manager):
# def get_random_username(self):
# while True:
# random_username = uuid4().hex[:30] # generate a random username
# if not User.objects.filter(username=random_username).exists():
# return random_username

# def schoolFactory(self, klass, name, password, login_id=None):
# user = User.objects.create_user(
# username=self.get_random_username(),
# password=password,
# first_name=name,
# )

# return Student.objects.create(
# class_field=klass, user=user, login_id=login_id
# )

# def independentStudentFactory(self, name, email, password):
# user = User.objects.create_user(
# username=email, email=email, password=password, first_name=name
# )

# return Student.objects.create(user=user)


# class Student(models.Model):
# class_field = models.ForeignKey(
# Class,
# related_name="students",
# null=True,
# blank=True,
# on_delete=models.CASCADE,
# )
# # hashed uuid used for the unique direct login url
# login_id = models.CharField(max_length=64, null=True)
# user = models.OneToOneField(
# User,
# related_name="student",
# null=True,
# blank=True,
# on_delete=models.CASCADE,
# )
# pending_class_request = models.ForeignKey(
# Class,
# related_name="class_request",
# null=True,
# blank=True,
# on_delete=models.SET_NULL,
# )
# blocked_time = models.DateTimeField(null=True, blank=True)

# objects = StudentModelManager()

# def is_independent(self):
# return not self.class_field

# def __str__(self):
# return f"{self.user.first_name} {self.user.last_name}"


# def stripStudentName(name):
# return re.sub("[ \t]+", " ", name.strip())

from common.models import Student
110 changes: 56 additions & 54 deletions codeforlife/user/models/teacher.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,68 @@
from django.db import models
# from django.db import models

from .user import User
from .school import School
# from .user import User
# from .school import School


class TeacherModelManager(models.Manager):
def factory(self, first_name, last_name, email, password):
user = User.objects.create_user(
username=email,
email=email,
password=password,
first_name=first_name,
last_name=last_name,
)
# class TeacherModelManager(models.Manager):
# def factory(self, first_name, last_name, email, password):
# user = User.objects.create_user(
# username=email,
# email=email,
# password=password,
# first_name=first_name,
# last_name=last_name,
# )

return Teacher.objects.create(user=user)
# return Teacher.objects.create(user=user)

# Filter out non active teachers by default
def get_queryset(self):
return super().get_queryset().filter(user__is_active=True)
# # Filter out non active teachers by default
# def get_queryset(self):
# return super().get_queryset().filter(user__is_active=True)


class Teacher(models.Model):
user = models.OneToOneField(
User,
related_name="teacher",
null=True,
blank=True,
on_delete=models.CASCADE,
)
school = models.ForeignKey(
School,
related_name="school_teacher",
null=True,
blank=True,
on_delete=models.SET_NULL,
)
is_admin = models.BooleanField(default=False)
blocked_time = models.DateTimeField(null=True, blank=True)
invited_by = models.ForeignKey(
"self",
related_name="invited_teachers",
null=True,
blank=True,
on_delete=models.SET_NULL,
)
# class Teacher(models.Model):
# user = models.OneToOneField(
# User,
# related_name="teacher",
# null=True,
# blank=True,
# on_delete=models.CASCADE,
# )
# school = models.ForeignKey(
# School,
# related_name="school_teacher",
# null=True,
# blank=True,
# on_delete=models.SET_NULL,
# )
# is_admin = models.BooleanField(default=False)
# blocked_time = models.DateTimeField(null=True, blank=True)
# invited_by = models.ForeignKey(
# "self",
# related_name="invited_teachers",
# null=True,
# blank=True,
# on_delete=models.SET_NULL,
# )

objects = TeacherModelManager()
# objects = TeacherModelManager()

def teaches(self, userprofile):
if hasattr(userprofile, "student"):
student = userprofile.student
return (
not student.is_independent()
and student.class_field.teacher == self
)
# def teaches(self, userprofile):
# if hasattr(userprofile, "student"):
# student = userprofile.student
# return (
# not student.is_independent()
# and student.class_field.teacher == self
# )

def has_school(self):
return self.school is not (None or "")
# def has_school(self):
# return self.school is not (None or "")

def has_class(self):
return self.class_teacher.exists()
# def has_class(self):
# return self.class_teacher.exists()

def __str__(self):
return f"{self.user.first_name} {self.user.last_name}"
# def __str__(self):
# return f"{self.user.first_name} {self.user.last_name}"

from common.models import Teacher
33 changes: 33 additions & 0 deletions codeforlife/user/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,20 @@
# def joined_recently(self):
# return timezone.now() - timedelta(days=7) <= self.date_joined

import typing as t

from common.models import UserProfile
from django.contrib.auth.models import User as _User
from django.db.models.query import QuerySet
from django.utils.translation import gettext_lazy as _

from . import auth_factor, otp_bypass_token, session
from .student import Student
from .teacher import Teacher


class User(_User):
id: int
auth_factors: QuerySet["auth_factor.AuthFactor"]
otp_bypass_tokens: QuerySet["otp_bypass_token.OtpBypassToken"]
session: "session.Session"
Expand All @@ -64,3 +69,31 @@ def is_authenticated(self):
return not self.session.session_auth_factors
except session.Session.DoesNotExist:
return False

@property
def student(self) -> t.Optional[Student]:
return self.new_student

@property
def teacher(self) -> t.Optional[Teacher]:
return self.new_teacher

@property
def otp_secret(self):
return self.userprofile.otp_secret

@property
def last_otp_for_time(self):
return self.userprofile.last_otp_for_time

@property
def developer(self):
return self.userprofile.developer

@property
def is_verified(self):
return self.userprofile.is_verified

@property
def aimmo_badges(self):
return self.userprofile.aimmo_badges
Loading

0 comments on commit 2108c96

Please sign in to comment.