I have tried to create a minimal working example of FormPreview of Django FormTools, but it did not work.
forms.py
This is a very simple form.
from django.forms import CharField, Form, Textarea
class TextForm(Form):
text = CharField(widget=Textarea)
preview.py
This is with slight adjustments just copied from the documentation. It is of curse incomplete but I did not changed it because I did not even got to a preview page of any kind.
from django.http import HttpResponseRedirect
from formtools.preview import FormPreview
class TextFormPreview(FormPreview):
def done(self, request, cleaned_data):
# Add stuff later, once I get to a preview.
return HttpResponseRedirect('/')
urls.py
Here must be some mistake, but I don't know how it should be correct. Should I remove the first URL? How does FormPreview know what the correct view to use is?
from django.conf.urls import url
from django import forms
from .forms import TextForm
from .preview import TextFormPreview
from . import views
urlpatterns = [
url(r'^$', views.textform),
url(r'^post/$', TextFormPreview(TextForm)),
]
views.py
My simple views.py.
from django.shortcuts import render
from .forms import TextForm
def textform(request):
if request.method == 'POST':
form = TextForm(request.POST)
if form.is_valid():
text = form.cleaned_data['text']
print(text)
if request.method == 'GET':
form = TextForm
context = {
'form': form
}
return render(request, 'text.html', context)
templates/text.html
And a simple template.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Text</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.manual_recipients.errors }}
{{ form.text }}
</div>
<input type="submit" value="OK"/>
</form>
</body>
</html>
templates/base.html
base.html is just an empty file. If I go to ^post/$ it says it requires a base.html. Why? I do not know.
As said, I did all the steps from the documentation but it is obviously incomplete. How do I fix it?
The default template for FormPreview extends base.html. and includes a single block content.
In your base.html, you need to include {% block content %}{% endblock %}. A minimal template would be:
<html>
<body>
{% block content %}{% endblock %}
</body>
</html>
See the docs on template inheritance for more info.
Related
I searched all around the web and didn't find an answer so hopefully this is not a duplicate. So I am trying to build a browser app using Django and are using some Jinja code in my html file, but the html file when loaded into a browser doesn't recognize Jinja code and only display raw code. In fact after some experimentation I found out that my browser doesn't display correctly any Jinja code. I checked and I've installed Jinja2 on my computer.
My html file looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Music FFT Visualizer</title>
<style></style>
</head>
{% block content %}
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload a Song</button>
</form>
</body>
{% endblock %}
<html>
and my view.py looks like this:
from django.shortcuts import render
from .forms import MusicVisualizerForm
from .models import MusicVisualizer
def lastSong(request):
MusicVisualizers = MusicVisualizer.objects.all()
MusicVisualizer_last = MusicVisualizers[len(MusicVisualizers)-1]
return render(request, 'MusicVisualizer/templates/MusicVisualizer.html', { 'MusicVisualizer' : MusicVisualizer_last})
def uploadSong(request):
if request.method == 'POST':
form = MusicVisualizerForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
form = MusicVisualizerForm()
return render(request, 'MusicVisualizer/templates/MusicVisualizer.html', {'form' : form})
my webpage looks like this:
My question: why i am not able to view search only ayan rand's book with classbased list view?
this is my function based view for store list, and i am retrieving all my book objects and rendering in HTML and it is working fine.
But using classbasedview "SearchBookDetail" i am not able to get the specified book details as denoted .
Views.py:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse,HttpResponseRedirect
from django.views.generic import TemplateView,ListView,DetailView
def store_listView(request,):
queryset=Book.objects.all()
context={
"objects_list":queryset
}
return render(request,'bookstores/store.html',context)
class SearchBookDetail(ListView):
template_name = "bookstores/store.html"
queryset = Book.objects.filter(author__icontains='Ayan Rand')
print("Ayan Rand query set", queryset)
Urls.py:
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from store.views import (Home,ContactView,LoginView,
store_listView,
SearchBookDetail,
book_createview,
QuoteslistView,
AyanRandBookDetail,
quotesFunctionView)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',Home.as_view()),
url(r'^contact/$',ContactView.as_view()),
url(r'^login/$',LoginView.as_view()),
url(r'^store/$',store_listView),
url(r'^store/AyanRandBookDetail/$',AyanRandBookDetail.as_view()),
url(r'^store/SearchBookDetail/$',SearchBookDetail.as_view()),
url(r'^quotes/$',quotesFunctionView)]
store.html:
{% extends "home.html" %}
{% block head_title %}Store || {{ block.super }} {% endblock head_title %}
{% block content %}
<head>
<meta charset="UTF-8">
<title>Store</title>
</head>
<h6>Books available</h6>
<ul>
{% for obj in objects_list %}
<li>{{obj}}<br>
{{obj.book_image}} <br>
{{obj.description}} <br>
{{obj.author}}<br>
{{obj.genre}}<br>
{{obj.price}}<br>
</li>
{% endfor %}
</ul>
{% endblock content %}
ListView sends its data to the template as object_list, not objects_list.
I am using django-allauth. I want the login and signup forms both on the home page of my website and not on '/accounts/login' or '/accounts/signup'
I have created a separate app. The following code is in views.py
from allauth.account.views import SignupView
from allauth.account.forms import LoginForm
class CustomSignupView(SignupView):
# here we add some context to the already existing context
template_name = 'index.html'
def get_context_data(self, **kwargs):
# we get context data from original view
context = super(CustomSignupView,
self).get_context_data(**kwargs)
context['login_form'] = LoginForm() # add form to context
return context
the following is in index.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button id="toggleForms">Toggle Forms</button>
<form method='post' action='/accounts/signup/' id='signup'>
{% csrf_token %}
<h1>blah</h1>
{{ form.as_p }}
<input type='submit' value='Sign Up'>
</form>
<form method='post' action='/accounts/login/' id='login'>
{% csrf_token %}
{{ login_form.as_p }}
<input type='submit' value='Log In'>
</form>
</body>
</html>
The forms work when the inputs are correct i.e. the form is valid. The problem is when the validation fails (in case of incorrect credential) the user is redirected to accounts/login and the error message is displayed. How to stop this redirect and show the error messages too on the home page?
It would probably be easier to override the template so that it looks like your index page. You can either specify a template with the name ('account/login.html'), or specify your own version of the URL, with a different template altogether:
from allauth.account.views import LoginView
...
url(r'^my-login/$', LoginView.as_view(template_name="index.html"), name="my-login"),
...
Neither of these are part of the public API for allauth, so use them at your own risk...
I'm new to Django and I'm still trying to get to grips with its features. I've created very simple project with Django 1.4.2 which has index page with simple form where you enter something and results page where your input is displayed after submission (the code is below).
After submission, I get error 403 and the following message:
A {% csrf_token %} was used in a template, but the context did not
provide the value. This is usually caused by not using
RequestContext. warnings.warn("A {% csrf_token %} was used in a
template, but the context did not provide the value. This is usually
caused by not using RequestContext.")
index.html
<!DOCTYPE html>
<head>
<title>Index page</title>
</head>
<body>
<div id="header">Welcome to index page</div>
<div id="content">
<p>Enter your name</p>
<form action="/result/" method="post" accept-charset="utf-8">{% csrf_token %}
<input type="text" name="answer">
<input type="submit" value="Send!">
</form>
</div>
</body>
result.html
<!DOCTYPE html>
<head>
<title>Result page</title>
</head>
<body>
<div id="header">Here is the result</div>
<div id="content">
<p>Your name is: {{ answer }}</p>
</div>
</body>
views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
def index(request):
return render_to_response('index.html')
def result(request):
p = request.POST['answer']
return render_to_response('result.html', {'answer': p}, context_instance=RequestContext(request))
I've looked into documentation and various examples on the Internet, but I don't understand what I'm doing wrong. If I disable django.middleware.csrf.CsrfViewMiddleware in settings.py, I get exactly what I want, but that's not the answer I'm looking for.
I appreciate help from more experienced Django ninjas :-)
Your index.html is rendered without RequestContext. Try this:
def index(request):
return render_to_response('index.html', context_instance=RequestContext(request))
I also recomend you to use more convenient shortcut render:
from django.shortcuts import render
def index(request):
return render('index.html')
From docs:
render() is the same as a call to render_to_response() with a
context_instance argument that forces the use of a RequestContext.
EDIT:
Thanks #nerdwaller for mentioning, newer versions now needs:
render(request, 'index.html', {params});
I was getting this error using Django 2.1, turned out that it was caused by make an ajax request in the template that was called by another ajax request. So, the solution was to add 'request=request' to my render function:
args = {'someargs': somevalues}
html = render_to_string(
'my_template.html', context=args, request=request)
return HttpResponse(html)
This may seem like a silly question but I can't find anything to help.
How would you create a logout button on every view like the one available in the admin page?
Use templates inheritance:
https://docs.djangoproject.com/en/dev/topics/templates/#template-inheritance
or include tag:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#include
Example with template inheritance:
We have a base template for all pages on our application:
base.html
<html>
<head>...</head>
<body>
logout # or use the "url" tag: {% url logout_named_view %}
{% block content %} {% endblock %}
</body>
</html>
other_pages.html
{% extends "base.html" %}
{% block content %}
<div class="content">....</div>
....
....
{% endblock %}
Now, we have a logout link on all pages inherited from the base.html
Example with include tag:
user_panel.html
<div class="user_panel">
logout
</div>
other_pages
<html>
<head>...</head>
<body>
{% include "user_panel.html" %}
...
...
</body>
</html>
I recommend for a solution to your problem using template inheritance
I wanted to extend the approved reply with my solution. What i did is:
from django.shortcuts import redirect
from django.contrib.auth import logout
If you want a method that checks if the user is already logged in you can create a function:
def UserLoggedIn(request):
if request.user.is_authenticated == True:
username = request.user.username
else:
username = None
return username
this checks if the user is already logged in and returns its username
then create a request function that checks if the username is not None (or just ommit the if statement)
def logout_view(request):
username = UserLoggedIn(request)
if username != None:
logout(request)
return redirect(your_home_view_here)
lastly just import your view into urls.py and create a path in urlpatterns
path('logout/', logout_view, name='logout')