Django: How to get the list of the usergroups and use that list (dictionary) as a choice options for a model field?

mahmudKabir Source

Scenario:

I have a field named "editor" in my model "Questions" as below:

CHOICE_LIST = (('0', 'Undefined'), ('staffGroup', 'staffGroup'), ('staffGroup02', 'staffGroup02'), ('staffGroup03', 'staffGroup03'), ('staffGroup04', 'staffGroup04'), ('staffGroup05', 'staffGroup05'),)
editor = models.CharField(max_length=350, default=0, choices=CHOICE_LIST, verbose_name='Responsibility')

the editor field has a choice list which I manually defined from the names of user groups.

Problem:

  1. How can I generate the list directly from the auth_grup table?
  2. How can I selectedly do that (as I may not need all of them, I only may need those groups which starts with 'staff' string)
  3. How can I make this list static (so deleting an entry from usergroup may not delete it from the list) or dynamic (will dynamically update the list with the change in auth_group table)?
pythondjangodjango-modelsmodelchoicefield

Answers

answered 6 days ago rtindru #1

Re 1: You can use a callable that returns all group. Example:

def getGroupNames():
    return Group.objects.all().values_list('name', flat=True)

You will still need to convert this to a tuple of ('short-name', 'human-readable-name')

If you want the same full names as short and human readable names in the tuple, you can do:

def getGroupNames():
    groups = Group.objects.all().values_list('name', flat=True)
    return zip(groups, groups)

And then use the same in the choice field

editor = models.CharField(max_length=350, default=0, choices=getGroupNames(), verbose_name='Responsibility')

Re 2: You can filter your query

def getGroupNames():
    return Group.objects.filter(name__starts_with='staff').values_list('name', flat=True)

Using choices is a presentation convenience. There is no restriction of the value that can be sent to the database, even coming from the front-end. For example, if you use the browser's inspect feature, you can edit the drop-down list, change one of the values and submit it. The back-end view will then happily consume it and save it to the database.

Meaning you will still be able to do this

obj = SomeModel.objects.get(pk=1)
obj.editor = 'Random Value not part of choices'
obj.save()

Re 3: The callable technique mentioned above is as static or as dynamic as you write it to be; this function will be evaluated when you make migrations and the values will be added as choices in the migration file. However, any serializers or forms that you write around this model will evaluate the choices time and time again.

Reference: https://zindilis.com/blog/2017/05/04/django-backend-validation-of-choices.html

comments powered by Disqus