Skip to content
This repository has been archived by the owner on Jul 8, 2023. It is now read-only.

enum validation #179

Open
vocabulista opened this issue Feb 16, 2023 · 4 comments
Open

enum validation #179

vocabulista opened this issue Feb 16, 2023 · 4 comments

Comments

@vocabulista
Copy link

vocabulista commented Feb 16, 2023

First of all: thank you very much for this library! I have a question regarding how to properly validate an enum.

This is my model:

class Lemma(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid_lib.uuid4, editable=False)
    word = models.CharField(max_length=100)
    language = models.CharField(max_length=3, null=True, blank=True)
    multiword_expression = models.BooleanField(default=False)
    related_lemmas = models.ManyToManyField('self', blank=True)
    related_meanings = models.ManyToManyField(Meaning, blank=True, related_name='lemma_related_meanings')

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

my enum:

@strawberry.enum
class Language(Enum):
    pal = "pal"
    eng = "eng"
    deu = "deu"
    ita = "ita"
    spa = "spa"
    fra = "fra"

and my type:

@gql.django.filters.filter(models.Lemma, lookups=True)
class LemmaFilter:
    id: relay.GlobalID
    word: gql.auto
    language: Language


@gql.django.type(models.Lemma, filters=LemmaFilter)
class Lemma(relay.Node):

    token_lemmas:  relay.Connection[gql.LazyType['Token', 'types.token']]
    comment_lemma: relay.Connection[gql.LazyType['Comment', 'types.comment']]

    id: relay.GlobalID
    word: gql.auto
    language: Language
    related_lemmas: List['Lemma']
    related_meanings: List[gql.LazyType['Meaning', 'types.meaning']]


@gql.django.input(models.Lemma)
class LemmaInput:
    word: gql.auto
    language: Language
    related_lemmas: gql.auto
    related_meanings: gql.auto


@gql.django.partial(models.Lemma)
class LemmaPartial:
    id: relay.GlobalID
    word: gql.auto
    language: Language
    related_lemmas: gql.auto
    related_meanings: gql.auto

This is the query and the error that I see:

image

I do not want to use django_choices_field. How can I avoid then this validation error? Thanks!

@bellini666
Copy link
Member

I think I know what is happening there:

In [3]: @strawberry.enum
   ...: class Language(enum.Enum):
   ...:     pal = "pal"
   ...:     eng = "eng"
   ...:     deu = "deu"
   ...:     ita = "ita"
   ...:     esp = "esp"
   ...:     fra = "fra"
   ...: 

In [4]: str(Language.deu)
Out[4]: 'Language.deu'

You are using a CharField, and when something that is not a str is passed to it it will call str(<var>) on it to send to the database.

In that specific case what you can do is use a StrEnum instead of Enum:

In [9]: @strawberry.enum
   ...: class Language(enum.StrEnum):
   ...:     pal = "pal"
   ...:     eng = "eng"
   ...:     deu = "deu"
   ...:     ita = "ita"
   ...:     esp = "esp"
   ...:     fra = "fra"
   ...: 

In [10]: str(Language.deu)
Out[10]: 'deu'

For curiosity, is there any reason why you are not using TextChoices (which is basically a StrEnum with a verbose name to be used by django). And why don't you want to use django-choices-field? It is not mandatory, just pure curiosity =P

@vocabulista
Copy link
Author

Thanks for your prompt reply. I did update python to 3.11 and it works!

That is an interesting question. Together with other colleagues we are working on a framework to be used primarily by linguists. We do know that we will be using ISO 639-3 codes. This is the reason for CharField(max_length=3) But as we expect to have different instances of the framework deployed, the set of languages allowed might vary. For this reason, we decided to modify the enum at API level and not at DB level in order to avoid running migrations.

Thanks again for your help and great work with this library!

@bellini666
Copy link
Member

That is an interesting question. Together with other colleagues we are working on a framework to be used primarily by linguists. We do know that we will be using ISO 639-3 codes. This is the reason for CharField(max_length=3) But as we expect to have different instances of the framework deployed, the set of languages allowed might vary. For this reason, we decided to modify the enum at API level and not at DB level in order to avoid running migrations.

Ah, just a FYI using choices in the field will just validate it at application level, it doess't create a constraint limiting the choices at dblevel.The django-choices-field also doesn't do that, it is just a shortcut to be able to define a CharField with choices more easily

@vocabulista
Copy link
Author

Ok. Thanks for the information!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants