I'm updating function based views to class based views and having issues re-establishing the link between campaign and books. My Book Model has a foreign key link to Campaigns.
campaign = models.ForeignKey(Campaign, on_delete=models.DO_NOTHING)
I have a ModelForm where I set the campaign_id and would like to get this from the CreateView.
class BookForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
author = kwargs.pop('author', None)
campaign_id = kwargs.pop('campaign_id', None)
super(BookForm, self).__init__(*args, **kwargs)
if campaign_id:
self.fields['campaign_id'].initial = campaign_id
campaign_id = forms.CharField(widget=forms.HiddenInput())
I followed this using dispatch and get_form_kwargs and my CreateView looks like
class BookCreateView(generic.CreateView):
model = Book
template_name = 'PromoManager/book_form.html'
form_class = BookForm
success_url = '/profile'
campaign_id = None
# Retrieves the campaign_id from url
def dispatch(self, request, *args, **kwargs):
self.campaign_id = kwargs.get("pk")
return super().dispatch(request, *args, **kwargs)
## Sends building id to the form
def get_form_kwargs(self, *args, **kwargs):
kwargs = super().get_form_kwargs(*args, **kwargs)
kwargs["campaign_id"] = self.campaign_id
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['campaign'] = Campaign.objects.get(pk=self.campaign_id)
context['title_label'] = "Create"
return context
def form_valid(self, form):
instance = form.save(commit=False)
instance.author = self.request.user
instance.campaign = Campaign.objects.get(id=form.cleaned_data['campaign_id'])
instance.save()
form.save_m2m()
return super().form_valid(form)
But it breaks the UpdateView which relies on the same form as the PK passed on the update view URL is the book pk. My UpdateView looks like:
class BookUpdateView(generic.UpdateView):
model = Book
template_name = 'PromoManager/book_form.html'
form_class = BookForm
success_url = '/profile'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title_label'] = "Update"
return context
def form_valid(self, form):
print(form)
form.save(commit=True)
return super().form_valid(form)
def form_invalid(self, form):
print(form.errors)
How can I pass a Campaign Id or instance to the form to populate it upon create and then maintain the value during any updates. This value should not be changeable. TY
So, I have a solution but would still be interested to hear whether its a good solution or problematic. I have used get_initial to pass values across to the ModelForm.
The init for BookForm(ModelForm) looks like:
and the CreateView looks like:
and finally UpdateView looks like:
My question would be if this is the most efficient way to get the data for update given it will already be in the form instance (or will it?)