Home > database >  Django: how to save instance to a foreign key field based on the fields equally
Django: how to save instance to a foreign key field based on the fields equally

Time:10-13

So I have a user model that has a foreign key relation with class/room, I want a user to be able to press one button and all the users/students would be equally distributed throughout the class/room foreign key based on fields from the model like age, height and other fields. so if there are 4 students 2 with age 14 and 2 with age 15 and there are two classes, the function should put one 14-year-old and one 15-year-old in 1 class and the same in the other class as well, just iterate through the users and distribute them by the selected field values equally, any resource or code snippet would be highly appreciated.

user model if needed

class User(AbstractBaseUser, PermissionsMixin):

class SEX(models.TextChoices):
    MALE = "MALE", "Male"
    FEMALE = "FEMALE", "Female"


id = models.UUIDField(
    primary_key=True, default=uuid.uuid4, editable=False, unique=True)
sex = models.CharField(
    _("Sex Type"), max_length=50, choices=SEX.choices, default=None, blank=True, null=True)
email = models.EmailField(
    _("Email"), max_length=254, unique=True, default=None, blank=True, null=True)
student_id = models.CharField(
    _("student id"), unique=True, max_length=10, blank=True, null=True)
firstname = models.CharField(max_length=250, blank=False, null=True)
middlename = models.CharField(max_length=250, blank=False, null=True)
lastname = models.CharField(max_length=250, blank=False, null=True)
grade = models.ForeignKey(Grade, verbose_name=_(
    "grade"), on_delete=models.SET_NULL, blank=True, null=True)
room = models.ForeignKey(Class, verbose_name=_(
    "class"), related_name="student_room", on_delete=models.SET_NULL, blank=True, null=True) // class model forignkey
age = IntegerRangeField(min_value=1, max_value=99,
                        default=25, blank=True, null=True)

image = models.ImageField(
    _("photo"), upload_to='user/Users/profile_pic', max_length=None, blank=False, null=True)
joined_date = models.DateTimeField(
    _("created at"), auto_now=False, auto_now_add=True)
has_rated = models.BooleanField(_("Has rated the app"), default=False)
...
class Meta:
    verbose_name = _("User")
    verbose_name_plural = _("Users")
    ordering = ('-joined_date',)

objects = CustomAccountManager()

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname']

def __str__(self):
    return self.firstname

CodePudding user response:

I have given a code snippet for you to find a solution.It might not be the efficient solution. But you shall have gist.

def assign_class(request, *args, **kwargs):
    age14_users = User.objects.filter(age=14).order_by('-joined_date')
    age14_users_pk_list=list(age14_users.values_list('pk', flat=True))

    age15_users = User.objects.filter(age=15).order_by('-joined_date')
    age15_users_pk_list=list(age15_users.values_list('pk', flat=True))

    age14_users_count = len(age14_users_pk_list)
    age15_users_count = len(age15_users_pk_list)

    classes= Class.objects.all()
    class_count = classes.count()
    class_pk_list=list(classes.values_list('pk', flat=True))
 
    slice = age14_users_count//class_count
    sliced_users_list_age14=[age14_users_pk_list[i:i slice] for i in range(0, len(age14_users_pk_list), slice)]  
    #output eg. [[1,2,3],[4,5,6],[7,8]]
    #User will be distributed to rooms rationally
    '''
    if we loop through sliced user clusters.. we can assign 
    each cluster to room rationally 
    '''
    new_class_pk_list = class_pk_list.copy()
    for lst in sliced_users_list_age14:
        for user_pk in lst:
            user = User.objects.get(pk=user_pk)
            user.room_id =new_class_pk_list[0]
            user.save()
        del new_class_pk_list[0] #delete the class after assigning
        #from copied list
            
    '''
    Now you can distribute the other cluster of group (eg. age15_users)
    like above
    '''

  • Related