Django generic view initial value in form - python

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})

Related

Update context of FormView only in certain condition

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

Django 'ListBlogPost' object has no attribute 'get_object'

here is my code. I am new in django. I am not understanding why I am getting this error 'ListBlogPost' object has no attribute 'get_object. anyone please help:
#views.py
class ListBlogPost(ListView,FormView):
model = Blog
template_name = 'blog.html'
form_class = BlogFrom
def get_success_url(self):
return reverse('blog')
def get_context_data(self, **kwargs):
data = super(ListBlogPost, self).get_context_data(**kwargs)
data['blog_admin_form'] = BlogFrom()
return data
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super(ListBlogPost, self).form_valid(form)

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')

How to work with the formset in CBV at the Django?

I have a form ProductCreateForm. It is necessary to insert the form SpeciallyPriceForm inside it.
I have a view for ProductCreateForm. But I don’t know how to process SpeciallyPriceForm in it either.
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
http_method_names = ['get', 'post']
def get_form_kwargs(self):
print('form')
kwargs = super(ProductsCreate, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def get(self, request, *args, **kwargs):
self.object = None
...
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
product = form.save(commit=False)
product.user = self.request.user
product.save()
if self.request.is_ajax():
return JsonResponse({'success': True, 'location': location})
else:
return redirect(location)
def form_invalid(self, form):
....
upd.
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
# template_name = 'products/product_form.html'
http_method_names = ['get', 'post']
def get_form_kwargs(self):
kwargs = super(ProductsCreate, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def get_context_data(self, *args, **kwargs):
print('ok')
ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
def get(self, request, *args, **kwargs):
self.object = None
if kwargs.get('slug'):
category = Category.objects.filter(slug=kwargs.get('slug')).first()
self.initial.update({'category': category})
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = self.get_form()
special_form = SpeciallyPriceForm(self.request.POST)
if form.is_valid() and special_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
product = form.save(commit=False)
I need the template as
<form ... >
{{ form }} /*product_form
{{ formset }} /* specially_price_form
</form>
upd2
models
class Product(models.Model):
category = models.ForeignKey(
Category, related_name='product',
verbose_name=_('category'), on_delete=models.SET_NULL, null=True,
)
forms
self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all())
def clean(self):
cleaned_data = super(ProductCreateForm, self).clean()
cd_category = cleaned_data.get('category')
views
form = self.get_form() #Error
I believe a formset is really to show the same form several times with different instances. What you want here is 2 forms. Add get_context data
def get_context_data(self, *args, **kwargs):
ctx=super().get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
def form_valid(self, form):
special_form = SpeciallyPriceForm(self.request.POST)
if special_form.is_valid():
...
else: error code and return to screen

Update two forms with one submit

I have one form and formset. I want to update them at the same time (with the same submit). Forms are rendered correct (with good data), but updated data is not written to db. Nether forms validation works. When it is one form it works perfect. Where could be the problem?
My view class:
class EventAdminPage(UpdateView):
form_class = CreateEventForm
second_form_class = modelformset_factory(EventTime, form = EventTimeForm, min_num=1, validate_min=True, extra=3)
model = Event
template_name = 'eventAdmin.html'
def get_context_data(self, **kwargs):
context = super(EventAdminPage, self).get_context_data(**kwargs)
event_times = EventTime.objects.filter(event = self.object).exclude(start_time = None)
context['participants'] = Participant.objects.filter(event = self.object)
context['event_times'] = EventTime.objects.filter(event = self.object).exclude(start_time = None)
context['event_time_formset_helper'] = event_time_formset_helper = EventTimeFormsetHelper()
context['formset'] = self.second_form_class(prefix='eventtime', queryset=event_times)
context['form'] = self.form_class(instance = self.object)
return context
def post(self, request, **kwargs):
self.object = self.get_object()
event_times = EventTime.objects.filter(event = self.object).exclude(start_time = None)
if 'update_event_form' in request.POST:
form = self.form_class(instance=self.get_object())
formset = self.second_form_class(queryset=event_times)
if form.is_valid() and formset.is_valid():
form.save()
formset.save()
return HttpResponseRedirect('/event-admin-%s' %self.kwargs['event_id'])
else:
return self.render_to_response(
self.get_context_data(form=form, formset=formset))
def get(self, request, **kwargs):
self.object = Event.objects.get(pk=self.kwargs['event_id'])
form = self.form_class
formset = self.second_form_class
context = self.get_context_data(object=self.object, form=form, formset=formset)
return self.render_to_response(context)
def get_object(self, queryset=None):
obj = Event.objects.get(pk=self.kwargs['event_id'])
return obj

Categories

Resources