Django FormView pass pk in success_url
Asked Answered
S

3

6

Assuming I have the following FormView and i want to pass the item.pk to some other view after the form is submitted. I guess i have to edit get_success_url() but i can't even figure out how to get item.pk from form_valid():

models.py

from django.db import models

class Book(models.Model):
    field1 = models.CharField(max_length=32)
    field2 = models.CharField(max_length=32)
    field3 = models.CharField(max_length=32)

    def __str__(self):
        return self.field1

forms.py

from django import forms
from .models import Book

class SomeForm(forms.ModelForm):

    field_order = ['field3', 'field2', 'field1']

    class Meta:
        model = Book
        fields = ['field1', 'field2', 'field3']

views.py

from django.shortcuts import render
from django.views.generic.edit import FormView
from .forms import SomeForm

class SomeView(FormView):
    form_class = SomeForm
    template_name = 'appname/form.html'
    success_url = reverse_lazy('somewhere')


    def form_valid(self, form):

        # save in Database
        item = form.save()

        # item.pk stores the saved pk 

        return super().form_valid(form)

    def get_success_url(self)
         # how can i get item.pk from form_valid() here and pass it to another view?
Sacristy answered 1/7, 2018 at 12:24 Comment(5)
You should really avoid saving something when you specify if it is valid. Now you basically have completely invalidated Django contracts, and as a result, several things might no longer work correctly.Saturninasaturnine
Is this by the way a ModelForm? In that case you better use ModelFormView, since this offers more convenience for this.Saturninasaturnine
Do you mean ModelFormMixin ? You may have an example how to use it ?Sacristy
no the mixin is used to "upgrade a Form to a ModelForm so to speak, but you can let SomeForm use the ModelForm subclass (in case it directly maps on a single model).Saturninasaturnine
To be honest, your comments confused me a little bit :-( I updated my code samples, maybe this helps to understand what i have and what i am looking for? btw form.save() is mentioned in many other answers, i thought it would be ok.Sacristy
P
13

You can do like below

class SomeView(FormView):
    form_class = SomeForm
    template_name = 'appname/form.html'    

    def form_valid(self, form):
        item = form.save()
        self.pk = item.pk
        return super(SomeView, self).form_valid(form)

    def get_success_url(self):
         #print(self.pk)
         return reverse('some_url', kwargs={'pk': self.pk})
Putrescine answered 2/7, 2018 at 9:42 Comment(1)
Looks like success_url is not needed in this case: your get_success_url() overrides it anyway.Pratte
C
5

You can access the pk from the object attribute like this:

class SomeView(CreateView):
    """
    """

    model = Model    
    
    def get_success_url(self) -> str:
        return reverse_lazy('success', kwargs={'pk': self.object.pk})
Cormac answered 4/10, 2022 at 17:22 Comment(0)
B
-1

I found something very straight forward:

views.py

class SomeView(FormView):
    ...
    context_object_name = 'object_name'
    ...

    def get_success_url(self)
        return reverse('some_url', kwargs={'pk': self.get_context_data()['object_name'].pk})
Bifrost answered 11/4, 2022 at 22:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.