1

In the view : I need to display a dropdown list of years starting from a fixed value (say 2005) to the current year. Now, this list, though dynamic, does not come from the database. Also, I want the list to expand as time goes by.

In the model : I want this field to be like an IntegerField(?) which saves values only from 2005 to, say, 3000, and throws a validation error otherwise.

What I could do - Make the dropdown as a ChoiceField in the View, and set up a validator for the model.

What I want - I want to use ModelForm in Django since this field, along with others in the form maps to the fields of my model. It means that I wont be defining fields in my Form, but only in the model. The question is, therefore, what should my approach be?

This I have tried so far-

class Member(models.Model):
    d = int(datetime.datetime.now().strftime("%Y"))
    ch = [(X,X) for X in range(2005,d)]
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    membership_type = models.IntegerField(validators=[validate_membership_type])
    batch = models.IntegerField(choices= ch)

This generates the form with desired select field but the values do not change. I replaced 'Years' by 'Minutes' to test it, and the range remains fixed with the upper limit as the number of minutes at the time of starting the server ,i.e., when the model gets created. I want this range to be determined by the view, i.e., when the form is loaded on the browser.

1 Answer 1

1

Firstly, this code does not belong in the model, but in the form.

Secondly, if you need things to be dynamic, they must go in the __init__ method, not at class level. So:

class MemberForm(forms.ModelForm):
    class Meta:
        model = Member
        fields = [..., 'batch', ...]

    def __init__(self, *args, **kwargs):
        super(MemberForm, self).__init__(*args, **kwargs)
        d = datetime.datetime.now().year
        ch = [(X,X) for X in range(2005, d)]
        self.fields['batch'].choices = ch
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Daniel for the quick reply. Just one thing though, what did you mean by 'this code does not belong in the model, but in the form' ? Are you referring to the first two lines and thus implying that such logic should not be a part of the model? (Because I need to define my model with the help of the rest of the 'code', no?)
Yes, I mean the dynamic choices stuff. Obviously the fields definitions are part of the model, but you should remove the choices from there completely.
Hi Daniel, the statement self.fields['batch'].choices = ch doesn't work because IntegerField of forms does not have a choices attribute (that of models class does). I changed it to self.fields['batch'].widget = forms.Select(choices=ch) and it worked. Please make this change in your answer and I will mark it as correct. Thanks for your help (y)

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.