Update context of FormView only in certain condition - python

I have a code in my FormView in Django:
class SearchView(LoginRequiredMixin, FormView):
template_name = "dic_records/search_form.html"
form_class = KokyakuForm
success_url = 'search'
fetched_data = []
def form_valid(self, form):
print(form.cleaned_data)
kokyaku_instance = FetchKokyaku(form.cleaned_data['name_search'])
err_check = kokyaku_instance.connect()
kokyaku_instance.get_data()
if err_check is False:
messages.error(self.request, "データを出力できませんでした")
return super(SearchView, self).form_valid(form)
kokyaku_list = list(kokyaku_instance.get_data())
if len(kokyaku_list) == 0:
messages.error(self.request, "検索のデータを見つけられませんでした")
return super(SearchView, self).form_valid(form)
self.fetched_data = kokyaku_list
return super(SearchView, self).form_valid(form)
def get_context_data(self, **kwargs):
"""Use this to add extra context."""
context = super(SearchView, self).get_context_data(**kwargs)
context['list'] = self.fetched_data
return context
And I would like to provide to template a list of values kokyaku_list from context variable, but only if my form is valid and data are fetched from kokyaku_instance.get_data().
The code above wont pass values

Related

how to use if in django class based view

i want to use if and i need to have a variable and that variable needs kwords
class ResetPassword(FormView):
template_name = 'reset_password.html'
form_class = ResetPasswordForm
def get_context_data(self, **kwargs):
context = super(ResetPassword, self).get_context_data(**kwargs)
context['uuid'] = kwargs.get('uuid')
context['base64'] = kwargs.get('base64')
return context
if (get_context_data['context']['uuid'] and get_context_data['context']['base64']) == (url_uuid and url_base64):
def form_valid(self, form):
user = User.objects.get(id= self.request.user.id)
user.set_password(form.cleaned_data['password'])
user.save()
return redirect('/login')

How do I keep the current user for a child form from a formset?

I don't fully understand the logic. In my model, the attachment has an author, and the post also has an author. But, I need to save two current users in Post and Attachment.
But only the current user is saved to the form, and not saved to the formset.
class PostCreateView(CreateView):
model = Post
template_name = 'modules/post/post_create.html'
form_class = PostForm
success_url = None
def get_context_data(self, **kwargs):
data = super(PostCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['formset'] = PostAttachmentFormSet(self.request.POST)
else:
data['formset'] = PostAttachmentFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
formset = context['formset']
with transaction.atomic():
form.instance.created_by = self.request.user
formset.instance.created_by = self.request.user #not working...
self.object = form.save(commit=False)
form.save_m2m()
if formset.is_valid():
formset.instance = self.object
formset.save()
return super(PostCreateView, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('main')
Solved the problem with CreateView. It turns out that you had to use a FOR loop to open each nested form inside the parent form.
class PostCreateView(SuccessMessageMixin, CreateView):
model = Post
template_name = 'modules/post/post_create.html'
form_class = PostForm
success_message = "Материал: %(title)s был добавлен на сайт!"
def get_context_data(self, **kwargs):
context = super(PostCreateView, self).get_context_data(**kwargs)
context['formset'] = PostAttachmentFormSet(instance=Attachment())
return context
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request.FILES)
formset = PostAttachmentFormSet(request.POST)
if form.is_valid() and formset.is_valid():
return self.form_valid(form, formset)
else:
return self.form_invalid(form, formset)
def form_valid(self, form, formset):
with transaction.atomic():
current_user = self.request.user
form.instance.created_by = current_user
self.object = form.save(commit=False)
attachments = formset.save(commit=False)
for attachment in attachments:
attachment.post_id = self.object.id
attachment.created_by = current_user
attachment.save()
form.save_m2m()
form.save()
print(form.cleaned_data, formset.cleaned_data)
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, formset):
return self.render_to_response(
self.get_context_data(form=form, formset=formset))
def get_success_url(self):
return reverse_lazy('file_list')

Django generic view initial value in form

i want to have default value in my form which should be current user's choice. For example, user chooses to give 5 for a movie and he should see 5 in form until he changes it.
views.py
class MovieDetailView(FormMixin, DetailView):
model = Movie
template_name = 'main/detail_movie.html'
context_object_name = 'movie'
form_class = RateForm
def get_context_data(self, **kwargs):
context = super(MovieDetailView, self).get_context_data(**kwargs)
context['form'] = RateForm(initial={'movie': self.object})
context['my_rate'] = Rate.objects.filter(
sender=self.request.user,
movie=self.get_object()).first()
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if request.method == 'POST':
if form.is_valid():
new_rate, _ = Rate.objects.update_or_create(
sender=self.request.user,
movie=self.object,
defaults={'choice': form.cleaned_data['choice']}
)
return JsonResponse({'rate': model_to_dict(new_rate)}, status=200)
else:
return self.form_invalid(form)
def get_success_url(self):
return reverse('detail_movie', kwargs={'slug': self.object.slug})
I was trying get_initial method but it still gives me '---' in form as default.
def get_initial(self):
return {'choice': Rate.objects.filter(movie=self.object, sender=self.request.user).first().choice }
Even something like this doesn't work
def get_initial(self):
return {'choice': 1 }
If you want to use FormMixin and get_initial method you need to use get_form method in get_context_data
class MovieDetailView(FormMixin, DetailView):
model = Movie
template_name = 'main/detail_movie.html'
context_object_name = 'movie'
form_class = RateForm
def get_initial(self):
initial = super(MovieDetailView, self).get_initial()
initial['movie'] = self.object # selected movie
rate = Rate.objects.filter( # attempt to get rate
movie=self.object,
sender=self.request.user
).first()
if rate is not None: # set rate choice only if it has been done before
initial['choice'] = rate.choice
return initial
def get_context_data(self, **kwargs):
context = super(MovieDetailView, self).get_context_data(**kwargs)
context['form'] = self.get_form() # use from mixin instead manual init
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if request.method == 'POST':
if form.is_valid():
new_rate, _ = Rate.objects.update_or_create(
sender=self.request.user,
movie=self.object,
defaults={'choice': form.cleaned_data['choice']}
)
return JsonResponse({'rate': model_to_dict(new_rate)}, status=200)
else:
return self.form_invalid(form)
def get_success_url(self):
return reverse('detail_movie', kwargs={'slug': self.object.slug})
Ok, i just had to input
'choice': Rate.objects.filter(movie=self.object, sender=self.request.user).first().choice
to my context['form'] where i already had initial:
def get_context_data(self, **kwargs):
context = super(MovieDetailView, self).get_context_data(**kwargs)
context['form'] = RateForm(
initial={
'movie': self.object,
'choice': Rate.objects.filter(movie=self.object, sender=self.request.user).first().choice
})
context['my_rate'] = Rate.objects.filter(
sender=self.request.user,
movie=self.get_object()).first()
return context
Put this in your form.
form = RateForm(initial={'choice': 1})

How can i get the pk from a cloned model instance in form_valid to use in get_success_url in an UpdateView?

class DomainRegistrationItemUpdateView(UpdateView):
model = DomainRegistrationItem
form_class = DomainAddYearsForm
template_name = "add_years.html"
def get_context_data(self, *args, **kwargs):
context = super(DomainRegistrationItemUpdateView,
self).get_context_data(**kwargs)
# tld_ppy Top Level Domain Price Per Year
context['tld_ppy'] = TLD.objects.get(
name='.%s' % (self.kwargs['domain_name'].split('.')[1])).yearly_price
return context
def get_object(self, queryset=None):
return DomainRegistrationItem.objects.get(domain=self.kwargs['domain_name'], purchased=True)
def get_success_url(self):
split_dn = self.kwargs['domain_name'].split('.')
namespace = split_dn[0]
sld = split_dn[1]
return reverse("domain_registraiton_item_detail", kwargs={
"pk": self.kwargs['pk'],
'namespace': namespace,
'second_level_domain': sld})
def form_valid(self, form):
f = form.save(commit=False)
working_dri = DomainRegistrationItem.objects.get(domain=self.kwargs['domain_name'])
working_dri.pk = None
working_dri.save()
working_dri.purchased = False
working_dri.years = f.years
f.save()
return super(DomainRegistrationItemUpdateView, self).form_valid(form)
The working_dri code is code that clones a DomainRegistrationItem under consideration by the view.
I want to get the pk from working_dri to usee in get_success_url. How can I do this? Thanks in advance for any and all help.
An UpdateView stores the object it saves to self.object, as we can see in the source code:
def form_valid(self, form):
"""If the form is valid, save the associated model."""
self.object = form.save()
return super().form_valid(form)
so we can make use of:
class DomainRegistrationItemUpdateView(UpdateView):
model = DomainRegistrationItem
form_class = DomainAddYearsForm
template_name = "add_years.html"
# …
def get_success_url(self):
split_dn = self.kwargs['domain_name'].split('.')
namespace = split_dn[0]
sld = split_dn[1]
return reverse("domain_registraiton_item_detail", kwargs={
"pk": self.object.pk,
'namespace': namespace,
'second_level_domain': sld})
def form_valid(self, form):
form.instance.pk = None
form.instance.purchased = False
form.instance.years = f.years
return super(DomainRegistrationItemUpdateView, self).form_valid(form)

How to use two different Django Form at the same template using class based view

I am using django class based view to create two forms (Thread, Message).
views.py
class ThreadForm(FormView):
template_name = 'thread.html'
form_class = ThreadModelForm
success_url = '/success'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
return super(ThreadForm, self).form_valid(form)
class MessageForm(FormView):
template_name = 'thread.html'
form_class = MessageModelForm
success_url = '/success'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
return super(MessageForm, self).form_valid(form)
Both are the rendering the same html file thread.html. Could anyone tell me how can I render both the forms in the same template?
thread.html
{{ form.as_p }}
UPDATE: I am using the view below but it is not working:
class MessageForm(FormView):
template_name = 'thread.html'
success_url = '/success'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
return super(MessageForm, self).form_valid(form)
def get_context_data(self, **kwargs):
context = super(MessageForm, self).get_context_data(**kwargs)
context['second_form'] = MessageModelForm
return context
use get_context_data method for this.
def get_context_data(self, **kwargs):
context = super(FormViewName, self).get_context_data(**kwargs)
context['second_form'] = SecondForm
return context
Then in your template you can use
{{ second_form.as_p }}
Also in your form_valid method you've to check for second_form validity as well.
I do it like this...
class SolicitudUpdate(UpdateView):
model = Solicitud
second_model = Persona
template_name = 'adopcion/solicitud_form.html'
form_class = SolicitudForm
second_form_class = PersonaForm
success_url = reverse_lazy('adopcion:solicitud_listar')
def get_context_data(self, **kwargs):
context = super(SolicitudUpdate, self).get_context_data(**kwargs)
pk = self.kwargs.get('pk', 0)
solicitud = self.model.objects.get(id=pk)
persona = self.second_model.objects.get(id=solicitud.persona_id)
if 'form' not in context:
context['form'] = self.form_class()
if 'form2' not in context:
context['form2'] = self.second_form_class(instance=persona)
context['id'] = pk
return context

Categories

Resources