1

I need a solution for this problem:

I would like to have MultiField widget for a "value" field. This field should allow to input two values (two input widgets), and user should choose which of these values is to be saved (two checkbox widgets). However, one of these values must be recalculated with respect to other field's value.

I've taken this approach: a MultiValueField with 4 fields:

class PriceDetailField(MultiValueField):
    use_net = BooleanField(required=False)
    net_value = DecimalField(required=False, decimal_places=2)
    use_gross = BooleanField(required=False)
    gross_value = DecimalField(required=False, decimal_places=2)

a MultiWidget:

class PriceDetailWidget(MultiWidget):
    use_net = CheckboxInput()
    net_value_widget = TextInput()
    use_gross = CheckboxInput()
    gross_value_widget = TextInput()

and a custom Form...

class PriceModelForm(ModelForm):
    value = PriceDetailField()

...which overrides default model form for a model:

class Price(models.Model):
    value = models.DecimalField(
        max_digits=19,
        decimal_places=2,
        default=Decimal(0),
        )

However, this solution seems to be messed up. In the form, I need to input all subfields (the MultiValueField subfields), otherwise "Please enter value" error appears (even though those fields are marked as required=False). Also, I must recalculate the mentioned value upon a save, having returned a tuple from the field with information which checkbox was checked and the corresponding text value, then replace the tuple with the decimal value in clean_value method of form (also, saving the checkboxes state in temporary fields....). I think such a design is very weak.

The form should work both on its own and as inline (this means, the value of the field which is used to calculate the returned value can or cannot change during save).

Is such a thing even possible?


And the root of the problem: I want to store prices of items as net prices, but I would like to allow users to input them as net or gross prices, and then recalculate gross price to net price with respect to product's VAT tax level (since VAT is assigned to product or service, not to the price). A product can have many prices, so a price is backlinked to the product by a foreign key.

Cheers, Tomek

Duncan Parkes
  • 1,902
  • 1
  • 15
  • 24
tomek
  • 25
  • 3

1 Answers1

0

The feature you're looking for on a MultiValueField (allowing the sub-fields to be required or not individually) is logged as a feature request on Django.

You could probably fix this for now by subclassing MultiValueField with a rewritten clean method based on the original and following suggestions from the bug report. You're not going to have a lot of the original MultiValueField left by that point though, and if you do, you should submit your patch to Django and put a note on the bug.

Ignoring for a moment the requiredness thing, have you written a compress method on your PriceDetailField? What does it look like? This is where you should be doing the work to turn your four sub-fields into a single field to save.

Duncan Parkes
  • 1,902
  • 1
  • 15
  • 24
  • I came through MultiValueField clean method and I realized that it calls compress. So, all that was to do was to properly implement compress method. Now, it returns calculated decimal (because, I linked the whole form to the field upon construction, so I can access the field that is required to calculate MVF's field value), throws ValidationError (if the combination of subfields is illegal) or returns None. I also had to reimplement _has_changed method of MultiWidget. No field logic is held in the form, except for passing form's reference to field. – tomek Sep 08 '11 at 07:04
  • Can you please specify how the MultiValueField's subfields can be accessed in the template, individually? – Cloud Artisans Aug 19 '13 at 18:24