I have a Django 2.1 views.py that I wanted to convert to Class Based View, I am NOT Django advanced user, and I know that I did translate the Functions the wrong way. The code was ment to serve a Bootstrap Modal Ajax form, and don't ask me to go see some solution already built out there, I tried everything, even the ones that worked fine in standalone, they are not compatible/conflict with my template (Maybe jquery or ..). I did convert List View and so far Create View, but I keep getting this Error :
UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
"A {% csrf_token %} was used in a template, but the context "
Here's my views.py that I want to convert to CBV :
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.template.loader import render_to_string
from .models import Book
from .forms import BookForm
from django.views.generic import TemplateView, ListView, DetailView, CreateView, UpdateView, DeleteView
#The Old function List view
#def book_list(request):
# books = Book.objects.all()
# return render(request, 'books/book_list.html', {'books': books})
#The New Class List view
class Book_list(ListView):
template_name = 'books/book_list.html'
model = Book
def save_book_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
books = Book.objects.all()
data['html_book_list'] = render_to_string('books/includes/partial_book_list.html', {
'books': books
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def book_create(request):
if request.method == 'POST':
form = BookForm(request.POST)
else:
form = BookForm()
return save_book_form(request, form, 'books/includes/partial_book_create.html')
def book_update(request, pk):
book = get_object_or_404(Book, pk=pk)
if request.method == 'POST':
form = BookForm(request.POST, instance=book)
else:
form = BookForm(instance=book)
return save_book_form(request, form, 'books/includes/partial_book_update.html')
def book_delete(request, pk):
book = get_object_or_404(Book, pk=pk)
data = dict()
if request.method == 'POST':
book.delete()
data['form_is_valid'] = True
books = Book.objects.all()
data['html_book_list'] = render_to_string('books/includes/partial_book_list.html', {
'books': books
})
else:
context = {'book': book}
data['html_form'] = render_to_string('books/includes/partial_book_delete.html', context, request=request)
return JsonResponse(data)
I've been strugling since 9 days now. asking around, asked even the developper of that code ... no answer..
I really appreciate it, thank you guys
You can try this to change you view's to class based view's
class BookList(ListView):
template_name = 'books/book_list.html'
model = Book
class BookCreate(CreateView):
template_name = "books/includes/partial_book_list.html"
model = Book
form_class = BookForm
success_url = 'success' #name of url you want to redirect to
class BookUpdate(UpdateView):
model = Book
form_class = BookForm
fields = ['name',] #field's you want to update
template_name = 'books/includes/partial_book_update.html'
success_url = 'success' #name of url you want to redirect to
class BookDelete(DeleteView):
model = Book
template_name = 'books/includes/partial_book_delete.html'
success_url = 'success'
Related
I am a student currently learning Django. When I register the product, I want to complete the product registration by specifying the product option, and I want to get the product_code of the option model from get. I wrote this code, but the get_object part keeps getting errors. There are currently 14 registered products, so I think there is an error like above, so please tell me how to solve it. I would appreciate it if you could let me know. I'd like to ask you very much.
views.py
from django.shortcuts import render, redirect, get_object_or_404
from zeronine.models import *
from .forms import ProductForm, OptionForm
# Create your views here.
def product_upload(request):
current_category = None
categories = Category.objects.all()
products = Product.objects.all()
slug = Product.slug
if request.method == "POST":
form = ProductForm(request.POST, request.FILES)
if form.is_valid():
product = Product()
product.name = form.cleaned_data['name']
product.benefit = form.cleaned_data['benefit']
product.detail = form.cleaned_data['detail']
product.target_price = form.cleaned_data['target_price']
product.start_date = form.cleaned_data['start_date']
product.due_date = form.cleaned_data['due_date']
product.category_code = form.cleaned_data['category_code']
product.image = request.FILES['image']
product.username = request.user
product.slug = slug
product.save()
if request.method == "POST":
form = OptionForm(request.POST)
if form.is_valid():
option = Option()
option.name = form.cleaned_data['option_name']
option.product_code = get_object_or_404(Product)
option.save()
return render(request, 'zeronine/list.html',
{'form': form, 'current_category': current_category, 'products': products, 'categories': categories, 'slug': slug})
else:
form = ProductForm()
return render(request, 'product/product_upload.html', {'form': form, 'current_category': current_category, 'products': products, 'categories': categories})
The model for the view is Chapter but it needs to call Book so that the chapter is saved to the right book.
def new_chapter(request, book_id):
"""Adds a new chapter"""
book = Book.objects.get(id=book_id)
if request.method != 'POST':
#No data submitted; create a blank form
form = ChapterForm()
else:
# POST data submitted; process data
form = ChapterForm(data=request.POST)
if form.is_valid():
new_chapter = form.save(commit=False)
new_chapter.book = book
new_chapter.save()
return redirect('fallen_worlds:book', book_id=book_id)
# Display a blank or invalid form.
context = {'book': book, 'form': form}
return render(request, 'fallen_worlds/new_chapter.html', context)
You can specify the book in the .form_valid(…) method [Django-doc]:
from django.views.generic.edit import CreateView
from django.urls import reverse
ChapterCreateView(CreateView):
model = Chapter
form_class = ChapterForm
template_name = 'fallen_worlds/new_chapter.html'
def form_valid(self, form):
form.instance.book_id = self.kwargs['book_id']
return super().form_valid(form)
def get_success_url(self):
return reverse(
'fallen_worlds:book',
kwargs={'book_id': self.kwargs['book_id']}
)
I am beginner in Django. My issue is that I updating my record but it's adding a new record instead of updating old one.
Where did I go wrong?
views.py
class EditProduct(TemplateView):
template_name = 'stock/editproduct.html'
def get(self, request, product_id):
productedit = get_object_or_404(Product, pk=product_id)
data=Product.objects.get(id=product_id)
form = EditProductForm(instance=data)
args = {'form':form, 'productedit':productedit}
return render(request, self.template_name, args)
def post(self, request, product_id):
form = EditProductForm(request.POST, request.FILES)
if form.is_valid():
productadded = form.save(commit=False)
productadded.saler = request.user
productadded.pub_date = timezone.datetime.now()
productadded.save()
return redirect('stock')
else:
args = {'form': form}
return render(request, self.template_name, args)
I'm assuming stock is the name of the app/folder that contains views.py, models.py, url.py.
views.py see here for documentation of UpdateViews.
from django.views.generic import UpdateView
from django.utils import timezone
from stock.models import Product
from stock.forms import EditProductForm
Class ProductUpdateView(UpdateView):
model = Product
form_class = EditProductForm
success_url = reverse_lazy('stock:product_list')
template_name = 'stock/editproduct.html'
def form_valid(self, form):
form.instance.saler = self.request.user
form.instance.pub_date = timezone.now()
return super().form_valid(form)
urls.py
from stock import views
app_name = 'stock'
urlpatterns = [
path('product/update/<int:pk>', views.ProductUpdateView.as_view(), name='product_update'),
path('product/list', views.ProductListView.as_view(), name='product_list'
]
The below snippet can be added to the html of the product page you want to update, this is generally the product details page generated by the details views class or function.
On that page add a button to take you to the update page passing in the id of the product you want to update.
<a class="btn btn-outline-warning waves-effect" href="{% url 'stock:product_update' pk=product.pk %}"> Update product</a>
I'm receiving this error "TemplateDoesNotExist at /bookmarks/list/1/delete_link/" when attempting to delete an object in Django.
In forms.py I have:
class DeleteForm(forms.ModelForm):
class Meta:
model = Link
fields = []
In views.py:
def delete_link(request, link_id):
link_to_delete = get_object_or_404(Link, id=link_id)
context_dict = {'link_id': link_id}
if request.method == 'POST':
form = DeleteForm(request.POST, instance=link_to_delete)
if form.is_valid():
link_to_delete.delete()
return HttpResponseRedirect('bookmarks/list')
else:
form = DeleteForm(instance = link_to_delete)
template_vars = {'form': form}
return render_to_response(request, 'bookmarks/delete_link.html', template_vars)
urls.py:
url(r'^list/(?P<link_id>\w+)/delete_link/$', views.delete_link, name='delete_link'),
embedded in list.html (template for displaying a list of links, I want delete options next to each):
<a href='/bookmarks/list/{{ link.pk }}/delete_link/'> Delete</a>
Here:
return render_to_response(request, 'bookmarks/delete_link.html', template_vars)
Django can't find your template. do you have it in your TEMPLATES_DIRS?
I am trying to make a search form for one of my classes. The model of the form is:
from django import forms
from django.forms import CharField, ModelMultipleChoiceField, ModelChoiceField
from books.models import Book, Author, Category
class SearchForm(forms.ModelForm):
authors = ModelMultipleChoiceField(queryset=Author.objects.all(),required=False)
category = ModelChoiceField (queryset=Category.objects.all(),required=False)
class Meta:
model = Book
fields = ["title"]
And the view I'm using is:
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template import RequestContext
from books.models import Book,Author
from books.forms import BookForm, SearchForm
from users.models import User
def search_book(request):
if request.method == "POST":
form = SearchForm(request.POST)
if form.is_valid():
form = SearchForm(request.POST)
stitle = form.cleaned_data['title']
sauthor = form.cleaned_data['author']
scategory = form.cleaned_data['category']
else:
form = SearchForm()
return render_to_response("books/create.html", {
"form": form,
}, context_instance=RequestContext(request))
The form shows up fine, but when I submit it I get an error: 'SearchForm' object has no attribute 'cleaned_data'
I'm not sure what's going on, can someone help me out? Thanks!
For some reason, you're re-instantiating the form after you check is_valid(). Forms only get a cleaned_data attribute when is_valid() has been called, and you haven't called it on this new, second instance.
Just get rid of the second form = SearchForm(request.POST) and all should be well.
I would write the code like this:
def search_book(request):
form = SearchForm(request.POST or None)
if request.method == "POST" and form.is_valid():
stitle = form.cleaned_data['title']
sauthor = form.cleaned_data['author']
scategory = form.cleaned_data['category']
return HttpResponseRedirect('/thanks/')
return render_to_response("books/create.html", {
"form": form,
}, context_instance=RequestContext(request))
Pretty much like the documentation.
I was facing the same problem,
I changed the code like this
if request.method == "POST":
form = forms.RegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
fname = form.cleaned_data.get('fname')
lname = form.cleaned_data.get('lname')
email = form.cleaned_data.get('email')
pass1 = form.cleaned_data.get('pass1')
pass2 = form.cleaned_data.get('pass2')
At times, if we forget the
return self.cleaned_data
in the clean function of django forms, we will not have any data though the form.is_valid() will return True.