Search code examples
djangocreate-view

prepoluate a generec createview


i want that a form is prepoluate with data

my model:

TYPE = (("S",'Swing'),
        ("R","Rapide"))
class valuation(models.Model):
    stock = models.ForeignKey("stock",on_delete=models.CASCADE,related_name='valuation',)
    date = models.DateField(auto_created=True)
    val_type = models.CharField(choices=TYPE, max_length=1,default='R')
    user = models.ForeignKey("users.User", on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.stock} - {self.date} - {self.val_type}"

my view:

class valuationCreateviewSwing(CreateView):
    template_name = "evaluation/evaluation_create.html"
    form_class = valuationModeform

    def get_form_kwargs(self): # prepopulate form
        kwargs = super(valuationCreateviewSwing, self).get_form_kwargs()
        stck = get_object_or_404(stock, pk=self.kwargs['pk'])
        kwargs['user'] = self.request.user
        kwargs['val_type'] = "S"
        kwargs['stock'] = stck
        return kwargs

    def get_context_data(self, **kwargs):
        # we need to overwrite get_context_data
        # to make sure that our formset is rendered
        data = super().get_context_data(**kwargs)
        if self.request.POST:
            data["val_detail"] = ChildFormset1(self.request.POST)
        else:
            data["val_detail"] = ChildFormset1()
        data.update({
            "typeVal": "Swing",})
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        val_detail_Swing = context["val_detail_Swing"]
        self.object = form.save(commit=False)
        # add data info neede about valuation model
        self.object = form.save()
        if val_detail_Swing.is_valid():
            val_detail_Swing.instance = self.object
            val_detail_Swing.save()
        return super().form_valid(form)

    def get_success_url(self):
        return reverse("stock:stock-list")

I've a child form in my view (this part works ok):

ChildFormset1 = inlineformset_factory(
    valuation, val_detail_Swing, form=valuationSwingModelform, can_delete=False)

I tried to use ge_for_kwargs but it seems not working as I've an error message : init() got an unexpected keyword argument 'user'


Solution

  • You can use get_initial() method:

    class valuationCreateviewSwing(CreateView):
        template_name = "evaluation/evaluation_create.html"
        form_class = valuationModeform
    
        def get_initial(self):
            query = self.request.GET
            return {
                    'user': self.request.user.pk
                    'val_type': "S",
                    'stock': self.kwargs.get('pk')
                }
         ...
    

    Or you should override __init__() method and stay to use get_form_kwargs()

    class valuationModeform(ModelForm):
        class Meta:
            model = Valuation
            fields = '__all__'
    
        def __init__(self, *args, **kwargs):
            user = kwargs.pop('user', None)
            val_type = kwargs('val_type', None)
            stock = kwargs.pop('stock', None)
            super().__init__(*args, **kwargs)
            # assign initial values
            self.fields['user'].initial = user
            self.fields['val_type'].initial = val_type
            self.fields['stock'].initial = stock