I`m using context processor to render form to the base template in my project and the form seems to work ok, except it doesnt show any errors for required fields being blank and etc. The page is simply reloaded even if fields are not filled in.
I used this approach in other project before, and it worked just fine, but now I cant really figure out what happened and why it is like so.
Here is my forms.py:
from django import forms
class VersionSelectorForm(forms.Form):
mode = forms.ChoiceField(widget=forms.RadioSelect(),
choices=(('live', 'Live'), ('history', 'History')),
initial='live',
required=True,
help_text='Required')
date = forms.DateField(widget=forms.TextInput(attrs={'class': 'datepicker'}),
required=True,
help_text='required')
def clean(self):
cleaned_data = super(VersionSelectorForm, self).clean()
mode = cleaned_data.get('mode')
date = cleaned_data.get('date')
if mode == 'history' and not date:
msg = 'Date should be picked if \'History\' mode selected'
self.add_error('date', msg)
view.py:
from django.shortcuts import redirect
from .forms import VersionSelectorForm
def select_version(request):
if request.method == "POST":
form = VersionSelectorForm(request.POST)
if form.is_valid():
print('I am valid')
mode = form.cleaned_data["mode"]
date = form.cleaned_data["date"]
if mode == "History":
request.session['selected_date'] = date
else:
request.session['selected_date'] = None
else:
form = VersionSelectorForm()
return redirect(request.META['HTTP_REFERER'])
context_processors.py:
from .forms import VersionSelectorForm
def VersionSelectorFormGlobal(request):
return {'version_selector_form': VersionSelectorForm()}
urls.py:
from django.contrib import admin
from diagspecgen import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^select_version/$', views.select_version, name='select_version'),
]
snippet from base.html:
<section><div>
<form method="post" action="{% url 'select_version'%}">
{% csrf_token %}
{{ version_selector_form.as_p }}
<button type="submit">Submit</button>
</form>
</div></section>
and of course I have added 'diagspecgen.context_processors.VersionSelectorFormGlobal' to context_processors list in settings.py.
Looking forward for any help and thanks in advance for that.
You should not use context processor to render your form, but instead pass it to the django shortcut render function.
You could do something like this:
def select_version(request):
if request.method == "POST":
form = VersionSelectorForm(request.POST)
if form.is_valid():
print('I am valid')
mode = form.cleaned_data["mode"]
date = form.cleaned_data["date"]
if mode == "History":
request.session['selected_date'] = date
else:
request.session['selected_date'] = None
else:
form = VersionSelectorForm()
return render(request, 'template.html', {'form': form})
Don't forget the import from django.shortcuts import render
Link to the doc: https://docs.djangoproject.com/en/2.0/topics/forms/#the-view
Related
I am trying to build a form to be used in 2 pages (index and contact).
Once the form performs method post, it will bring a page either success or failed (simple html page with few words).
I am stuck due to the error shown above and I’m still new in using Django.
Appreciate any help. Thank you
urls.py
from django.conf.urls import url
from django.conf.urls import include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app/', include('app.urls'))
]
app/url.py
from .views import *
app_name = "app"
urlpatterns = [
url(r'^home/$', home, name='home'),
url(r'^contact/$', contact, name='contact'),
url(r'^send_message/(?P<flag>\d+)/$', send_form, name='send_form'),
url(r'^send_message/success/$', success, name='success'),
url(r'^send_message/failed/$', failed , name='failed'),
]
views.py
from django.core.mail import send_mail
from .forms import MessagesForm
from django.conf import settings
rom django.shortcuts import render, redirect
def home(request):
empty_form = send_form(request)
cover_title = PageServiceCover.objects.latest('id').title
cover_text = PageServiceCover.objects.latest('id').text
context = {'cover_title': cover_title, 'cover_text': cover_text,'form':empty_form}
return render(request, 'index.html', context)
def send_form(request):
if request.method == 'POST':
form = MessagesForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
phone = form.cleaned_data['phone']
category = form.cleaned_data['category']
text = form.cleaned_data['text']
form.save()
subject=[name, phone, category]
send_mail(subject, text, email, [settings.EMAIL_HOST_USER], fail_silently=False)
return redirect('thanks', flag='success' )
else:
return redirect('not_working', flag='failed')
def success(request):
return render(request, 'thanks.html')
def failed(request):
return render(request, 'notworking.html')
index.html
<form action="{% url 'app:send_form' %}" method="POST" target="_blank">
{%csrf_token%}
{{form.as_p}}
<button type="submit"> Send Message </button>
</form>
Your url need a flag
url(r'^send_message/(?P<flag>\d+)/$', send_form, name='send_form'),
change view and pass flag from template
def send_form(request, flag):
if request.method == 'POST':
form = MessagesForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
phone = form.cleaned_data['phone']
category = form.cleaned_data['category']
text = form.cleaned_data['text']
form.save()
subject=[name, phone, category]
send_mail(subject, text, email, [settings.EMAIL_HOST_USER], fail_silently=False)
return redirect('thanks', flag='success' )
else:
return redirect('not_working', flag='failed')
I am following a tutorial in which we will create a form to hold simple object parameters.
Here's the code:
forms.py
from django.forms import ModelForm
from .models import Item
class ItemForm(ModelForm):
class Meta:
model = Item
fields = ['item_name', 'item_desc', 'item_price', 'item_image']
models.py
from django.db import models
class Item(models.Model):
def __str__(self):
return self.item_name
item_name = models.CharField(max_length = 200)
item_desc = models.CharField(max_length= 200)
item_price = models.IntegerField()
item_image = models.CharField(max_length=500, default ="https://i.jamesvillas.co.uk/images/jvh/holiday-destinations/resort/food-placeholder.jpg" )
urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.index, name = 'index'),
path('item/', views.item, name = 'item'),
path('info/', views.info, name = "info"),
path('<int:item_id>/', views.detail, name = "detail" ),
#add form
path('add', views.create_item, name = "create"),
]
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Item
from django.template import loader
from .forms import ItemForm
#Some code here
def create_item(request):
form = ItemForm(request.POST or None)
if (form.is_valid()):
form.save()
return redirect('food/index')
return render(request, 'food/item-form.html', {'form': form})
food/item-form.html
<form method = "POST">
{% csrf_token %}
{{ form }}
<button type= "Submit" >Save</button>
</form>
Now when I go to http://localhost:8000/food/add, it displays an empty page! I have followed the tutorial the exact same way then why is My project not working?
correct your views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
Help me please to understand how to make the delete button, its must to delete a Cat
class Cat(models.Model):
class Meta():
db_table = "cat"
paw = models.IntegerField(default=4)
name = models.CharField(max_length=30, null=False, default='Cat')
age = models.IntegerField(default=False, null=False)
species = models.CharField(max_length=50, blank=True)
hairiness = models.IntegerField(default=False, null=False)
def __str__(self):
return self.name
This is my views.py, hope you can help. (it's need for my job interview on Monday)
from django.shortcuts import render, get_object_or_404
from .models import Cat
from .forms import CatForm
from django.shortcuts import redirect
def home(request):
template = "base.html"
queryset = Cat.objects.all()
context = {
"object_list": queryset
}
return render(request, template, context)
def new_cat(request):
if request.method == "POST":
form = CatForm(request.POST)
if form.is_valid():
cat = form.save(commit=False)
cat.save()
return redirect('/', pk=cat.pk)
else:
form = CatForm()
return render(request, 'new_cat.html', {'form': form})
def cat_edit(request, pk):
cat = get_object_or_404(Cat, pk=pk)
if request.method == "POST":
form = CatForm(request.POST, instance=cat)
if form.is_valid():
cat = form.save(commit=False)
cat.save()
return redirect('/', pk=cat.pk)
else:
form = CatForm(instance=cat)
return render(request, 'new_cat.html', {'form': form})
site is asc to addd more details, but i just don't know what else, i can add.
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^new/$', views.new_cat, name='new_cat'),
url(r'^edit/(?P<pk>[0-9]+)/$', views.cat_edit, name='cat_edit'),
]
At first, you should create a cat_delete view, which should look something like this:
def cat_delete(request, pk):
cat = get_object_or_404(Cat, pk=pk) # Get your current cat
if request.method == 'POST': # If method is POST,
cat.delete() # delete the cat.
return redirect('/') # Finally, redirect to the homepage.
return render(request, 'template_name.html', {'cat': cat})
# If method is not POST, render the default template.
# *Note*: Replace 'template_name.html' with your corresponding template name.
Then, you should map this view in your urls.py:
from django.conf.urls import url
from . import views
app_name = 'cats'
# Note that app_name is added here!
# It is used as a namespace in order to reverse your urls better.
# See usage in template.
urlpatterns = [
# ...
url(r'^delete/(?P<pk>[0-9]+)/$', views.cat_delete, name='cat_delete')
]
In your template, you should create a form with delete button, which will simply send a POST request to the delete view:
<form action="{% url 'cats:cat_delete' cat.id %}" method="post">
{% csrf_token %}
<input type="submit" value="Delete cat">
</form>
Look closely on the form's action:
{% url 'cats:cat_delete' cat.id %}
Here I am using the app_name from urls.py that I previously added in order to resolve your urls by name, not by path. Now cats:cat_delete will evaluate to cats/delete/<pk>. And of course you pass the cat.id.
This should do the trick with deleting instance of your Cat model. Hope I helped.
I have a contact page for my website. The contact form is working but I want to add a background image to this page (which is saved in the database).But how can I combine my email(request) and a query to get the image ?
views.py
from django.core.mail import send_mail, BadHeaderError
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .forms import ContactForm
def email(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
subject = form.cleaned_data['subject']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(subject, message, from_email, ['admin#example.com'])
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('./success')
return render(request, "contact/email.html", {'form': form})
def success(request):
return HttpResponse('Success! Thank you for your message.')
models.py
from django.db import models
class Background(models.Model):
name = models.CharField(max_length=200, null=False)
image = models.ImageField(upload_to='./background/', default=None)
def __str__(self):
return self.name
urls.py
from django.conf.urls import url
from . import views
app_name = 'contact'
urlpatterns = [
url(r'^$', views.email, name='email'),
url(r'^success/$', views.success, name='success'),
]
You could retrieve the image on your view:
def get_background():
try:
background = Background.objects.get(name="your image name") # add your filters where to get the image
if background.image and background.image.url:
return background.image.url
except Background.DoesNotExist:
return
def email(request):
if request.method == 'GET':
form = ContactForm()
else:
...
...
# add the background to context
return render(request, "contact/email.html", {'form': form, 'background_img': get_background()})
And in your HTML (it's just a exemple, always try to style your site with a separate css file):
...
<div {% if background_img %}style="background: url('{{background_img}}') center no-repeat;"{% endif %}>
...
processor_for.py
from django import forms
from django.http import HttpResponseRedirect
from mezzanine.pages.page_processors import processor_for
from .models import Book
class BookForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
#processor_for(Author)
def author_form(request, page):
form = BookForm()
if request.method == "POST":
form =BookForm(request.POST)
if form.is_valid():
# Form processing goes here.
redirect = request.path + "?submitted=true"
return HttpResponseRedirect(redirect)
return {"form": form}
models.py
from django.db import models
from time import time
class Book(models.Model):
book_name= models.CharField(max_length=200, unique = True)
def __unicode__(self):
return self.book_name
views.py
def create_book (request):
if request.POST:
form = BookForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/all/')
else:
form = BookForm()
args= {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_Book.html', args)
urls.py
urlpatterns += patterns('',
url(r'^/xyz/$', create_book))
create_Book.html
<form action="/xyz/" method="post" enctype="multipart/form-data">{% csrf_token %}
{{form.as_ul}}
<input type="submit" name="submit" value="create"/>
</form>
This is what i am doing but still i am unable to access form. Where i am doing wrong. will be grateful to you. Please mark that what's wrong in code?
as per you code and your explanation in question .please see your code in urls.py
urlpatterns += patterns('',
url(r'^xyz/$', create_book)) # you should write like ^xyz/$
Please follow django doc
Two Syntax Problems:
1) Always define your processor name in " " like #processor_for("Author")
2) urls for page processors like :
url("^xyz/$", "mezzanine.pages.views.page", {"slug": "Author"}, name="Author"),