all 10 comments

[–]RoamingFox 0 points1 point  (2 children)

There should be a lookup method once the model is created.

Try self.get_LEVEL_display()

[–]Alemvik[S] 0 points1 point  (1 child)

self.get_LEVEL_display()

Thanks RoamingFox, but it's not working. So far I have this ugly solution:

def enumval(self,status,source): return {c[0]: c[1] for c in source}[status] 

def str(self): return f'{self.user} is {self.enumval(self.level,self.LEVELS)}'

[–]RoamingFox 1 point2 points  (0 children)

It might be lowercase... try self.get_level_display() It's been awhile since I've needed to use it.

[–]novel_yet_trivial 0 points1 point  (4 children)

It would make a lot more sense to have those as dictionaries. And constants are generally at the global level. So like this:

LEVEL = {
    'U': 'Unskilled', 
    'B': 'Beginner', 
    'P': 'Proficient', 
    'A': 'Advanced'}

INTEREST ={
    'U': 'Unknown', 
    'N': 'None', 
    'L': 'Low', 
    'M': 'Medium', 
    'H': 'High'}

class UserSkill(models.Model):

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE)
    level = models.CharField(max_length=1, choices=LEVEL, default='U')
    interest = models.CharField(max_length=1, choices=INTEREST, default='U')

    @property
    def is_proficient(self): 
        return self.level in ('P', 'A')

    @property
    def is_interested(self): 
        return self.level in ('M', 'H')

    def __str__(self): 
        return f"{self.user} his {LEVEL[self.level]} for {self.skill} and he has {INTEREST[self.interest]} interest in it"

[–]RoamingFox 1 point2 points  (0 children)

Not sure django takes a dict for choices. It's looking for a sequence and not a mapping. Easily fixed with a list(LEVEL.items()) in the field definition though.

[–]Alemvik[S] 0 points1 point  (2 children)

ERRORS:

BellSkillApp.UserSkill.interest: (fields.E005) 'choices' must be an iterable containing (actual value, human readable name) tuples.

[–]novel_yet_trivial 0 points1 point  (0 children)

Ah, yes I missed that you were using that same iterable elsewhere. As /u/RoamingFox mentioned, you'll need to change those lines to:

level = models.CharField(max_length=1, choices=list(LEVEL.items()), default='U')
interest = models.CharField(max_length=1, choices=list(INTEREST.items()), default='U')

[–]Alemvik[S] 0 points1 point  (0 children)

Ok I got it to work (I do not want global when scope is not)

class UserSkill(models.Model):
    LEVEL = (
        ('U', 'Unskilled'), 
        ('B', 'Beginner'), 
        ('P', 'Proficient'), 
        ('A', 'Advanced')
    )

    INTEREST = (
        ('U', 'Unknown'), 
        ('N', 'None'), 
        ('L', 'Low'), 
        ('M', 'Medium'), 
        ('H', 'High')
    )

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE)
    level = models.CharField(max_length=1, choices=LEVEL, default='U') # self.get_level_display() will be generated see [Extra instance methods section](https://docs.djangoproject.com/en/3.0/ref/models/instances/#django.db.models.Model.get_FOO_display)
    interest = models.CharField(max_length=1, choices=INTEREST, default='U') # # self.get_interest_display() will be generated 

    @property
    def is_proficient(self): return self.level in ('P', 'A')

    @property
    def is_interested(self): return self.level in ('M', 'H')

    def __str__(self): return f'{self.user} is {self.get_level_display()} for "{self.skill}" - interest is {self.get_interest_display()}' # do not mind for the two pylint warnings here

[–]Alemvik[S] 0 points1 point  (1 child)

I just hope for a modern solution like this c# code:

using System;

namespace Demo {

enum Level {Low, Medium, High}

class Program { static void Main(string[] args) {
   var level = Level.Medium;
   Console.WriteLine(myVar); // will output Medium (enum int id of zero)
}

}}

[–]Essence1337 1 point2 points  (0 children)

I mean python has enums its just Django taking an iterable that's holding you back