1

I'm trying to get all users who are employers. So what I did was I filter the users where the id can be found in the "employer" field of any (other) user. However this gives me the following error:

TypeError: int() argument must be a string, a bytes-like object or a number, not 'builtin_function_or_method'

View:

# Get all employers
class Employers(viewsets.ModelViewSet):
    queryset = CustomUser.objects.all()
    serializer_class = CustomUserSerializer

    def list(self, request):
        #queryset = CustomUser.objects.all();
        queryset = self.queryset.filter(id__in=CustomUser.objects.filter(employer=id))    #this gives me an error
        serializer = CustomUserSerializer(queryset, many=True)
        return Response(serializer.data)
    

Model (standard stuff):

# CustomUser model
class CustomUser(AbstractBaseUser):
    username = None
    email = models.EmailField(verbose_name='email address', max_length=255, unique=True)
    date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)

    employer = models.ForeignKey("self", blank=True, null=True, on_delete=models.DO_NOTHING)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = MyUserManager()

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        return self.is_admin

    def has_module_perms(selfself, app_label):
        return True;
    

I'm not sure what I'm doing wrong. Any suggestions?

3
  • what you are passing in id where the error occurs. I mean int or object? Commented Jul 23, 2020 at 10:55
  • @PruthviBarot: the builtin id function: docs.python.org/3/library/functions.html#id Commented Jul 23, 2020 at 11:14
  • @PruthviBarot id of CustomUser. So int. Commented Jul 23, 2020 at 11:19

1 Answer 1

1

You can filter with an F-expression [Django-doc] to refer to another column:

from django.db.models import F

class Employers(viewsets.ModelViewSet):
    queryset = CustomUser.objects.all()
    serializer_class = CustomUserSerializer

    def get_queryset(self, *args, **kwargs):
        return CustomUser.objects.filter(employer=F('pk'))

This thus makes a query that looks like;

SELECT customuser.*
FROM customuser
WHERE customuser.employer = customuser.id

or you can filter the relation in reverse to get CustomUsers that employ at least one person:

class Employers(viewsets.ModelViewSet):
    queryset = CustomUser.objects.all()
    serializer_class = CustomUserSerializer

    def get_queryset(self, *args, **kwargs):
        return CustomUser.objects.filter(customuser__isnull=False).distinct()

This constructs a query that looks like:

SELECT DISTINCT customuser.*
FROM customuser
JOIN customuser u2 ON u2.employer = customuser.id
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for your answer but I think this query isn't correct? Correct me if I'm wrong but I think this query selects customusers where their employer is the same as their id. So you only get the users who are their own employer? Whereas I simply want all employers.
@SJ19: in that case it is the latter. The question is, what are the employes of an employer? I would think then it refers to itself. But the second query lists all CustomUsers who have at least one CustomUser that has them as employer.
Employers don't have employers (null) :). Second query works! But I honestly have no clue what you're doing here, care to explain? Like what does customuser__isnull=False do, and what is distinct? There doesn't seem to be any reference to the employer field which I don't get.
@SJ19: no, but then it would perhaps be more elegant to link it to themselves, since then it is not a NULLable field, and moving "up" in the hierarcy is thus more elegant. Anyway, the latter should produce customusers that have at least one employee.
@SJ19: it means we make a LEFT OUTER join on the employer relation in reverse, and because of the __isnull=False filter, it thus is a simle INNER JOIN. The .distinct() is necessary, since otherwise we would return the same CustomUser multiple times, one for each employee.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.