0

I've got a model of UserCoupon that a user can create and edit. Upon edit, I only want them to be able to edit the 'code' field on the instance of UserCoupon if there are no orders associated with that code. When there are orders associated with that coupon code, rather than outputting {{form.code}} on the edit coupon form, I'm outputting {{form.instance.code}}. When the user attempts to submit the form, I get an error saying that the field is required.

How can I make this field not required or otherwise address this situation so that the user can submit the form when one of the fields defined for the model form shows up in the template as an instance of the field rather than an input box?

Models.py

class UserCoupon(models.Model):
    code = models.CharField(max_length=15, unique=True)
    amount = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)

forms.py

class EditUserCouponForm (forms.ModelForm):

    class Meta:
        model = UserCoupon

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user',None)
        super(EditUserCouponForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned_data = super(EditUserCouponForm, self).clean()

template

{% if coupon_order_count > 0 %}

   {{form.instance.code}}

{% else %}

    {{form.code}}

{% endif %}

Thanks!

Jason Howard
  • 1,464
  • 1
  • 14
  • 43

3 Answers3

0

Simply add blank=True to the model field:

class UserCoupon(models.Model):
    code = models.CharField(max_length=15, unique=True, blank=True)

See this question for a good explanation on the difference between blank and null.

Lord Elrond
  • 13,430
  • 7
  • 40
  • 80
0

Probably you can do it like this:

class EditUserCouponForm(forms.ModelForm):

    class Meta:
        model = UserCoupon
        fields = ['code']

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user',None)
        super(EditUserCouponForm, self).__init__(*args, **kwargs)
        if self.instance and self.instance.order_set.all().exists():  #checking if there are any orders with this coupon
             self.fields['code'].widget.attrs['disabled'] = 'disabled'

And in views, make sure when editing pass the instance like this:

def coupon_view(request, pk):
     coupon = UserCoupon.objects.get(pk=pk)
     form = EditUserCouponForm(request.POST or None, user=request.user, instance=coupon)
     if request.method == "GET":
          return render('template', context={'form':form})

Probably you don't need to use coupon_order_count in template

ruddra
  • 50,746
  • 7
  • 78
  • 101
0

I used this in my form and it worked:

def __init__(self, *args, **kwargs):
    self.user = kwargs.pop('user',None)     
    self.coupon_order_count = kwargs.pop('coupon_order_count',None)        
    super(EditUserCouponForm, self).__init__(*args, **kwargs)

    if int(self.coupon_order_count) > 0:        
        self.fields['code'].required = False
Jason Howard
  • 1,464
  • 1
  • 14
  • 43