views:

34

answers:

1

I've got a form for which I need to set a few values before validation. I'm trying:

if request.method == 'POST':
    reservation_form = ReservationForm(request.POST, initial={'is_reservation':True, 'user':request.user})

But it doesn't work. If I exclude the 'user' field from the (model)form, I get a null-constraint error, if I do include it, I get a validation error instead. So either it ignores the initial value because I've excluded the field, or the request.POST data trumps it, even when that value is not posted.

So how am I supposed to do this?


class ReservationForm(ModelForm): # TODO: abstract this and shipment form
    service_types = MultipleChoiceField(widget=MultiColumnCheckboxSelect(columns=2), choices=ServiceTypes,
    initial=[ServiceTypes.OPEN_TRANS], error_messages={'required': 'Please select at least one service type.'})
    payment_methods = MultipleChoiceField(widget=MultiColumnCheckboxSelect(columns=2), choices=PaymentMethods,
    error_messages={'required': 'Please select at least one payment method.'})
    payment_times = MultipleChoiceField(widget=MultiColumnCheckboxSelect(columns=2), choices=PaymentTimes, required=True,
    error_messages={'required': 'Please select at least one payment type.'})

    class Meta:
    model = Shipment
    exclude = ['headline', 'created', 'updated', 'expiry_date', 'status', 'accepted_bid', 'pickup_address', 'dropoff_address', 'billing_address', 'target_price']
    widgets = {
        'pickup_earliest': TextInput(attrs={'class':'date'}),
        'pickup_latest': TextInput(attrs={'class':'date'}),
        'dropoff_earliest': TextInput(attrs={'class':'date'}),
        'dropoff_latest': TextInput(attrs={'class':'date'}),
        'additional_info': WarningTextArea,
    }
+1  A: 

Ok, I hope I've now understand the problem correctly:

You have a ReservationForm which has no user and no is_reservation field. Because of that, it doesn't make any sense to set initial={'user': ...} because user is not part of that form (and neither is is_reservation).

On the other hand, you are having a Reservation model which is populated from some values of the form and an additional user id, as well as an is_reservation boolean.

So, generally you write something like that:

form = ReservationForm() # you migth want to set inital values here
if request.method == 'POST':
    form = ReservationForm(request.POST)
    if form.is_valid():
        data = form.cleaned_data
        reservation = Reservation() # create a new model

        # copy the values from the form to your new model
        reservation.payment_method = data['payment_methods']
        reservation.payment_time = data['payment_time']

        # set some additional values for the model (which are required)
        reservation.user_id = request.session['user_id'] # for example
        reservation.is_reservation = True

        # save the reservation (all required fields, including the user_id are now set)
        reservation.save()

Please note that this is just a example. I haven't seen your model class yet, so your model might look a bit different. But I think you will be able to adapt it.

Update

I think the following might work (but you will have to exclude the user and is_reservation as you already mentioned).

form = ReservationForm(request.POST)
reservation = form.save(commit=False)
reservation.user = request.user
reservation.is_reservation = True
reservation.save()
tux21b
No... sorry, you're mistaken. The ReservationForm *does* inherit an `is_reservation` and `user` field from the model, I just don't want to render them. `is_reservation` should always be True (it'll be false in another form that shares the same model), and `user` is always `request.user`. It *would* make sense to set `initial=`, *it just doesn't work*. You gave me an idea though... I just `exclude` both fields, and then `is_valid()` won't trip on them, and then I can set them properly inside the `form.is_valid` block.
Mark
PS: An easier way to do your example would be `reservation = ReservationForm(commit=False)`. Then you don't need to copy any values...
Mark
Well, I guess you are right in that the form *doesn't* have those fields... but only when I put them in the `exclude` list.. I'm indifferent to whether or not they're in that list, I just want the darn thing to work :p Excluding them and then setting them inside `is_valid` should work tho.
Mark
Ah, ok. I havent looked at the `Meta`... Adding a `exclude` will work imho. But you need to provide the values somewhere else (initial can't work, because if you don't render the fields, the field can not have an initial value during the rendering). And PS: I normally use WTForms and SQLAlchemy, and write `myform.populate_model(mymodel)` there :D
tux21b
Yes... that's exactly the problem I was having. I'll take a look at WTForms... I kind of hate Django forms anyway.
Mark
Switching technology whenever you encounter a problem might not be a solution either... Is `reservation = ReservationForm(commit=False); reservation.user = request.user; reservation.is_reservation=True; reservation.save()" not working correctly?
tux21b
(+ the exclude you mentioned before)
tux21b