简体   繁体   中英

how to implement ModelChoiceField in Django

I am trying to create an input selection from database model fields and I have tried using ModelChoiceField but I keep getting an error I don't know how to solve. I need help.

Here are the models

class WeeklySavingsDeposit(models.Model):

    WEEKLY_SAVE_DEPOSIT_STATUS_PENDING = 'Pending'
    WEEKLY_SAVE_DEPOSIT_STATUS_APPROVED = 'Approved'
    WEEKLY_SAVE_DEPOSIT_STATUS_DENIED = 'Denied'

    WEEKLY_SAVE_DEPOSIT_STATUS_CHOICES = ((WEEKLY_SAVE_DEPOSIT_STATUS_PENDING, 'Pending'), (WEEKLY_SAVE_DEPOSIT_STATUS_APPROVED, 'Approved'), (WEEKLY_SAVE_DEPOSIT_STATUS_DENIED, 'Denied'))

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateTimeField(default=timezone.now)
    savings_title = models.CharField(max_length=100, null = True, blank=True)
    amount = models.FloatField()
    dep_proof = models.ImageField(upload_to='deposit_proofs')
    status = models.CharField(max_length = 40, choices = WEEKLY_SAVE_DEPOSIT_STATUS_CHOICES, default='Pending')
    dep_tag = models.IntegerField(default=0)


    def __str__(self):
        return f'{self.user.username} WeeklySaveDeposit'
class WeeklySaving(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created = models.DateTimeField(default=timezone.now)
    title = models.CharField(max_length = 100, default = 'Weekly Savings Title')
    duration = models.CharField(max_length=40, choices=WEEKLY_SAVE_DURATION_CHOICES, default ='2 Months')
    completion_date = models.DateTimeField(null=True)
    amount = models.FloatField()
    target_amount = models.FloatField(null=True)
    status = models.CharField(max_length= 40,choices = WEEKLY_SAVE_STATUS_CHOICES, default='Pending')
    week_save_day = models.CharField(max_length =100, choices=WEEKLY_SAVE_DAY_CHOICES, default='Friday')
    amount_saved = models.FloatField()

My Forms.

class StartWeeklySaveForm(forms.ModelForm):

   title = forms.CharField(label = 'Savings Title', required=True)
   amount =  forms.FloatField(label='Amount to Save Weekly? (in Naira):', min_value=WeeklySaving.MIN_WEEKLY_SAVE, max_value=WeeklySaving.MAX_WEEKLY_SAVE, required=True, widget=forms.TextInput(attrs={'placeholder': 'Input the amount you want to save weekly. Minimum 500'}))

   class Meta:
       model = WeeklySaving
       fields = ["title", "amount", "duration", "week_save_day"]


class DepositWeeklySaveForm(forms.ModelForm):
       amount = forms.FloatField(label='Enter Amount in (Naira)', min_value=WeeklySaving.MIN_WEEKLY_SAVE, max_value=WeeklySaving.MAX_WEEKLY_SAVE, required=True, help_text='How much to deposit? Minimum 500',)
   dep_proof = forms.ImageField(label='Upload a Proof of Payment', help_text='teller or transaction receipt as image')

   class Meta:
       model = WeeklySavingsDeposit
       fields =["savings_title", "amount", "dep_proof"]

In my Views.py i have this

@login_required
def weekly_save(request):
    startwksave_form = StartWeeklySaveForm(request.POST or None, request.FILES)
    depwksave_form = DepositWeeklySaveForm(request.POST or None, request.FILES)
    user=request.user
    depwksave_form.fields['savings_title'] = WeeklySaveDepositModelChoiceField(WeeklySaving.objects.filter(user=user), empty_label="(Select savings)",required=True)
    depwksave_form.fields['amount'] = WeeklySaveDepositAmountModelChoiceField(WeeklySaving.objects.filter(user=user), empty_label="(Select savings amount)",required=True)

I have a fields.py as follows


from savings.models import WeeklySaving, WeeklySavingsDeposit
from django.forms import ModelChoiceField


class WeeklySaveDepositModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        result = obj.title
        return str(result)


class WeeklySaveDepositAmountModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        result = obj.amount
        return float(result)

in my template the form appears like this.. Form Template View

I am able to select the savings title and the amount from the WeeklySaving object which is what I want but when I submit the form it shows the error "Username Saving" must be a float. which means it is actually saving the input as 'Username Saving' instead of the selected saving title and amount.

How can I solve this problem please I need help. I am still new using django.

thanks for your help.

In general, it always gets hard with multiple forms in the same view. So if you split them into 2 views it would be much easier. Maybe it is possible to create one object from the other one? It is even worse (i think) that both forms do have the field "amount". Maybe it is possible to rename one of them.

Another big problem is this: DepositWeeklySaveForm().amount = forms.FloatField and this depwksave_form.fields['amount'] = WeeklySaveDepositAmountModelChoiceField This cannot work. WeeklySaveDepositAmountModelChoiceField should reference a ForeginKey, not a FloatField. so add to your models:

class WeeklySavingsDeposit(models.Model):
    weekly_savings = models.ForeignKey(WeeklySaving, on_delete=models.CASCADE)
    ...

I would recommend changing everything to a class based view eg CreateView and use get_form_kwargs to pass the user. Something like

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

Then you can set the field in the forms.py like this:

class DepositWeeklySaveForm(forms.ModelForm):
    weekly_savings = forms.ModelMultipleChoiceField(queryset=None)
    required=True, help_text='How much to deposit? Minimum 500',)
   dep_proof = forms.ImageField(label='Upload a Proof of Payment', help_text='teller or transaction receipt as image')

   class Meta:
       model = WeeklySavingsDeposit
       fields =["savings_title", "amount", "dep_proof", "weekly_savings"]

    def __init__(self, user, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['weekly_savings'].queryset = WeeklySaving.objects.filter(user=user)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM