Reputation: 35
I am new to Django and have been working on a project where I am trying to have choice fields dependent on bool values attached to the current user. I have this in the model
user = models.OneToOneField(user_model, on_delete=models.CASCADE)
####
I_CAT = models.BooleanField(default=False)
I_DOG = models.BooleanField(default=False)
I_PAW = models.BooleanField(default=False)
I_OPTIONS = [
[('star'), ('Star')],
When(I_CAT=True, then=Value([('cat'), ('Cat')])),
]
icon = models.TextField(choices=I_OPTIONS, default='star')
I am looking to have it so that when the value I_CAT for the current user is set to True it will add that option to our choices list which is used as choices list for icon. I don't really know the best way to approach this. I have tried to use When and if statements in the model file itself and also in the views for this page. I haven't managed to get anything to work yet the closest I got was this
if I_CAT:
I_OPTIONS.append([('cat'), ('Cat')])
This succeeds in adding something to the options list but it doesn't actually check if I_CAT is true or not and just adds it every time no matter what. I also read on another post that if statements inside a model are a bad idea so idk. Any guidance would be appreciated!
EDIT: I added this code to the Form as suggested by Brobin. I had to add an additional if statement to keep the option from being re-added every time the page was refreshed. Everything is now working as intended!
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
cat = [('cat'), ('Cat')]
dog = [('dog'), ('Dog')]
paw = [('paw'), ('Paw')]
choices = [
[('star'), ('Star')],
]
if self.instance.I_CAT:
if cat not in choices:
choices.append(cat)
if self.instance.I_DOG:
if dog not in choices:
choices.append(dog)
if self.instance.I_PAW:
if paw not in choices:
choices.append(paw)
self.fields['icon'].choices = choices
icon = forms.ChoiceField(required=True)
Upvotes: 0
Views: 3063
Reputation: 3326
I would rethink the models, so that the form is dynamic and based on a query. Something like this. This has the added bonus of not needing to add more booleans for new icons.
class Icon(models.Model):
code = models.CharField(max_length=16)
name = models.CharField(max_length=16)
class Profile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
icons_unlocked = models.ManyToManyField(Icon)
icon = mdoels.ForeignKey(Icon)
Then in your form, you can set the queryset choices for the field based on what the user has available.
class IconSelectForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['icon'].queryset = self.instance.icons_unlocked.all()
class Meta:
model = Profile
fields = ['icon']
If you don't want to change the models, you could do a similar thing with your booleans in the form
class IconSelectForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
choices = []
if self.instance.I_CAT:
choices.append(('cat', 'Cat'))
self.fields['icon'].choices = choices
class Meta:
model = Profile
fields = ['icon']
Upvotes: 1