Search code examples
djangoformsforeign-keys

Django Foreign key in hidden form field


I'd like to hide a Foreign Key field in a form created from a Model in a View. Here is the Model :

class Order(models.Model):
    class Meta:
        ordering = ['unity_price']
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    user = models.ForeignKey(authModels.User, on_delete=models.CASCADE, default=1)
    order_quantity = models.IntegerField(default=0)
    unity_price = models.FloatField(default=0)
    end_validity_date = models.DateTimeField(default=timezone.now() + datetime.timedelta(days=30))
    is_sell = models.BooleanField(default=True)

    def __str__(self):
        if self.is_sell:
            return 'sell ' + str(self.order_quantity) + ' ' + self.item.item_text + ' at ' + str(self.unity_price)
        return 'buy ' + str(self.order_quantity) + ' ' + self.item.item_text + ' at ' + str(self.unity_price)

Here is the Form :

from .models import Order

class OrderForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(OrderForm, self).__init__(*args, **kwargs)
        self.fields['user'].widget = HiddenInput()
        self.fields['item'].widget = HiddenInput()

    class Meta:
        model = Order
        fields = ('item', 'user', 'order_quantity', 'unity_price', 'end_validity_date', 'is_sell',)

And here is the View :

class DetailView(FormMixin, generic.DetailView):
    model = Item
    template_name = 'bourse/detail.html'
    form_class = OrderForm

    def get_success_url(self):
        return reverse('bourse:detail', kwargs={'pk': self.object.id})

    def get_context_data(self, **kwargs):
        context = super(DetailView, self).get_context_data(**kwargs)
        context['form'] = OrderForm(initial={'post': self.object})
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        form = self.get_form()
        form.fields['item'].initial = self.get_object()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        model_instance = form.save(commit=False)
        model_instance.user = self.request.user
        model_instance.item = self.get_object()
        print (model_instance.item)
        model_instance.save()
        return super(DetailView, self).form_valid(form)

It does work well for field 'user', but not for field 'item'. I don't know what to put in model_instance.item (that should be the object shown by the current view) or in form.fields['item'].initial (that should also be the object of the current view).

Regards,


Solution

  • Take the foreign key items out of the fields in your model form meta. Those are the fields that will be passed on to your form. So take:

     class Meta:
        model = Order
        fields = ('item', 'user', 'order_quantity', 'unity_price', 'end_validity_date', 'is_sell',)
    

    and use only:

    class Meta:
            model = Order
            fields = ('order_quantity', 'unity_price', 'end_validity_date', 'is_sell',)
    

    Putting those values back in through the form_valid works well if you need them.