Django 'ListBlogPost' object has no attribute 'get_object' - python

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)

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

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

in django CreateView, how do I add field and send that field as a context to template?

I know this is very beginner question but I still don't get it even after I read https://docs.djangoproject.com/en/1.9/ref/class-based-views/generic-editing/
so I have this createView right...
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'main/add_post.html'
def form_valid(self, form):
self.object = form.save(commit=False)
# any manual settings go here
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(PostCreateView, self).dispatch(request, *args, **kwargs)
and in add_post.html I want to use
hotCat = Category.objects.get_hotCat()
how do I use that hotCat in add_post.html?
You add variables into the context by overriding the get_context_data() method.
def get_context_data(self, **kwargs):
ctx = super(PostCreateView, self).get_context_data(**kwargs)
ctx['hotCat'] = Category.objects.get_hotCat()
return ctx

Categories

Resources