I'm having a problem with saving and updating a value to my database.
View:
def code_prof_edit(request, ampCode):
user_code = get_object_or_404(CodeUser, pk=ampCode)
if request.method =='POST':
form = CodeUserForm(request.POST, instance=user_code)
if form.is_valid():
form.save()
return HttpResponseRedirect('/codes/' + user_code.ampCode)
else:
form = CodeUserForm(instance=user_code)
return render_to_response('edit_code_user.html', {'user_code':user_code, 'form':form})
Relevant template form tag:
<form action="." method="POST"> {% csrf_token %}
{{form.as_p}}
<input type="submit" value="Save" />
</form>
Using the post method, the form correctly renders in the browser with all of the original values pre-populated, but if I change the values and click submit, none of the changes are made. Everything seems to work correctly in that the user is redirected to the correct page which means the save must have been called, but the info typed isn't being saved. Any and all help would be appreciated.
Edit entire view function:
from django.shortcuts import render_to_response, get_object_or_404
from django.http import *
from django.template import RequestContext
from codeuser.models import CodeUser
from codeuser.forms import CodeUserForm
import pdb
def code_prof_edit(request, ampCode):
user_code = get_object_or_404(CodeUser, pk=ampCode)
if request.method =='POST':
pdb.set_trace()
form = CodeUserForm(request.POST, instance=user_code)
if form.is_valid():
form.save()
return HttpResponseRedirect('/codes/' + user_code.ampCode)
else:
return render_to_response('home.html')
else:
form = CodeUserForm(instance=user_code)
return render_to_response('edit_code_user.html', {'user_code':user_code, 'form':form})
Edit: Figured it out. In the html form tag, the action attribute was incorrect. "." wasn't working, I needed "./edit" to get the correct result. Also, excluding that attribute all together worked perfectly too.
Related
I've created objects in the admin page of my app, but I'm unable to call the object in my html template. I will put the views and the html lines below
from django.shortcuts import render, redirect
from .models import *
from .forms import *
def index(request):
tasks = Task.objects.all()
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {'tasks': tasks, 'form': form}
return render(request, 'todo_app/list.html')
{% for task in tasks %}
<div class="task-container">
<p>{{task}}</p>
</div>
{% endfor %}
You forgot to send context to template:
Optional arguments
context
A dictionary of values to add to the template context. By default, this is an empty dictionary. If a value in the dictionary is callable, the view will call it just before rendering the template.
context = {'tasks': tasks, 'form': form}
return render(request, 'todo_app/list.html', context)
I'm trying to make a workflow where the user enters data on one page, then has to check the data and tick a tickbox to accept the T&C's. So the code has to check that the checkbox is checked before going on, but doesn't care until the second step.
It's not a bound field and I think that's the problem - I don't need a model just to handle a workflow, and I don't want to have to store, in a database, a simple ephemeral field in a form!
I'm running Django 2.1.5.
I've tried every possible combination of:
test_form.fields['tickbox'].value - doesn't exist, which is ridiculous
test_form.fields['tickbox'] == False - value doesn't change at all
request.POST['tickbox'] seems to go missing?
views.py
from django.http import HttpResponse
from django.template import loader
from django.forms import Form, CharField, BooleanField
class test_form(Form):
name = CharField()
tickbox = BooleanField(required=False, initial=False)
def testview(request):
if request.method == 'POST':
testform = test_form(request.POST)
if testform.fields['tickbox'] == True:
do_things()
else:
dont_do_things()
else:
testform = test_form()
template = loader.get_template('testform.html')
context = { 'testform : userform,
}
return HttpResponse(template.render(context, request))
I should be able to test the value of the field and get a changing response depending on if the user has ticked the box or not - I seem to get True regardless?
Here is a way how to solve your issue using Class Based Views and Function Based Views:
So, first:
forms.py:
from django import forms
class CheckboxForm(forms.Form):
name = forms.CharField()
tickbox = forms.BooleanField(required=False, initial=False)
def clean_tickbox(self):
'''Here we can check if the checkbox is checked or not'''
tickbox = self.cleaned_data.get('tickbox')
if not tickbox:
# Raise an error if the checkbox is not checked
raise forms.ValidationError("You must select this option")
# And return the value
return tickbox
With a class based view:
views.py:
from django.views import View
from django.contrib import messages
class CheckboxView(View):
template_name = 'checkbox.html'
form_class = forms.CheckboxForm
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
# check if the form is valid
if form.is_valid():
# Use Django builtin messages framework
messages.success(request, "Checked!")
else:
messages.error(request, "not checked!")
return render(request, self.template_name, {'form': form})
With function based views:
from django.contrib import messages
def checkbox_func(request, *args, **kwargs):
template = 'checkbox.html'
if request.method == 'POST':
form = forms.CheckboxForm(request.POST)
# Check if the form is valid
if form.is_valid():
messages.success(request, "Checked!")
else:
messages.error(request, "Not checked!")
else:
form = forms.CheckboxForm()
return render(request, template, {'form': form})
urls.py:
from django.urls import path
from YOUR_APP import views
urlpatterns = [
# ... Your URLS
# Class Based Views
path('checkbox/', views.CheckboxView.as_view(), name="checkbox"),
# Function Based Views
path('checkbox2/', views.checkbox_func, name="checkbox_v2")
]
And your template: checkbox.html:
{% for message in messages %}
{{message}}
{% endfor %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
Demo:
First of all, yes it is perfectly possible to have FormFields without them being declared in a Model.
You seem to be trying to do form validation on your own when django already handles simple cases like this for you. Let's start by looking at the documentation of BooleanField:
Validates that the value is True (e.g. the check box is checked) if
the field has required=True
Since that is exactly what you want to validate we can change the field definition:
tickbox = BooleanField(required=True, initial=False)
Since the documentation told us that django takes care of validating that the checkbox is actually checked there is no need for the custom validation code anymore. Let's look at the view next and refactor it:
def testview(request):
if request.method == 'POST':
testform = test_form(request.POST)
# check if the form is valid (that includes the checkbox being checked)
if testform.is_valid():
do_things()
else:
dont_do_things()
else:
testform = test_form()
template = loader.get_template('testform.html')
context = {'testform': userform} # added a closing single tick
return HttpResponse(template.render(context, request))
So instead of doing custom validation you just call the .is_valid() method of your Form instance to run validation. If you want to access any of the fields instead of using testform.fields[fieldname] you'd do testform.cleaned_data[fieldname] which only accesses fields that have been validated.
For more information on form processing in general I highly recommend reading through django's Working with forms.
I simply use the "cleaned_data" to check if the field is not part of the model but its just a form field.
so in your case this will be in your view
if testform.cleaned_data['tickbox'] == True:
do_things()
else:
dont_do_things()
I'm having multiple forms around my website.
However, a have a particular form that is working in the home page (index.html), but when coping this particular form in a section of my site it doesn't work anymore (on this section, if I return to home everything works as expected).
What am I missing?
Views.py:
from django.shortcuts import render, HttpResponse, HttpResponseRedirect
from .models import Treasure, TamaniosCantidades
from .forms import TreasureForm, TamaniosCantidadesForm, LoginForm
from django.contrib.auth import authenticate, login, logout
# Create your views here.
def index(request):
treasures = Treasure.objects.all()
form = TreasureForm()
tamanioscantidades_form = TamaniosCantidadesForm()
return render(request, 'main_app/index.html', {'treasures': treasures,
'form': form,
'tamanioscantidades_form': tamanioscantidades_form})
def productos(request):
treasures = Treasure.objects.all()
form = TreasureForm()
return render(request, 'main_app/productos.html', {'treasures': treasures,
'form': form})
def die_cut(request):
tamanioscantidades_form = TamaniosCantidadesForm()
return render(request, 'main_app/die-cut-stickers.html', {'tamanioscantidades_form': tamanioscantidades_form})
def post_tamanioscantidades(request):
form = TamaniosCantidadesForm(request.POST)
if form.is_valid():
tamanioscantidades = TamaniosCantidades(tamanios=form.cleaned_data['tamanios'],
cantidades=form.cleaned_data['cantidades'])
# tamanioscantidades = tamanioscantidades_form.save(commit = False)
# tamanioscantidades.usuario = request.user
tamanioscantidades.save()
return HttpResponseRedirect('/')
def post_treasure(request):
form = TreasureForm(request.POST)
if form.is_valid():
treasure = Treasure(name=form.cleaned_data['name'],
value=form.cleaned_data['value'])
treasure.save()
return HttpResponseRedirect('/')
urls.py:
app_name = 'main_app'
urlpatterns = [
path('', views.index),
path('productos/', views.productos),
path('productos/die-cut-stickers', views.die_cut, name='die-cut-stickers'),
path('post_url/', views.post_treasure, name='post_treasure'),
path('post_url_tamanioscantidades/', views.post_tamanioscantidades, name='post_tamanioscantidades'),
]
*html**:
<div class="col-md-6 border border-primary rounded border-3">
<div class="m-5">
<div class="row">
<form action="post_url_tamanioscantidades/" method="post">
{% csrf_token %}
{{ tamanioscantidades_form.as_p }}
<input type="submit" value="Submit"/>
</form>
</div>
</div>
As I said, this form works in home, but when coping the same code in a section of my site the submit button does not save the form in database.
It returns:
Page not found (404)
Request Method: POST
Request URL: http://127.0.0.1:8000/productos/post_url_tamanioscantidades/
Using the URLconf defined in gallito.urls, Django tried these URL patterns, in this order:
admin/
productos/
productos/die-cut-stickers [name='die-cut-stickers']
post_url/ [name='post_treasure']
post_url_tamanioscantidades/ [name='post_tamanioscantidades']
accounts/
The current path, productos/post_url_tamanioscantidades/, didn't match any of these.
The problem is the form is being submitted to http://127.0.0.1:8000/productos/post_url_tamanioscantidades/ which does not exist instead you want it to submit at http://127.0.0.1:8000/post_url_tamanioscantidades/
So in your form html start the form action with /
<form action="/post_url_tamanioscantidades/" method="post">
What is the Django way of creating a User?
I am not talking about the super user, just a simple form for users and creating an account
The Django docs cover the topic of authentication quite well, and Django itself ships with views for login, logout, password change, and reset. For registration, you'll have to create your own view, something like this:
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.shortcuts import render
def create_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse("User created successfully!")
else:
form = UserCreationForm()
return render(request, 'auth/create_user.html', {'form': form})
This uses Django's built-in User creation form, which expects a username and two passwords, for verification. Your template would look something like this:
<form action='/create-user/' method='post'>
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
Registration is not a part of Django framework, AFAIK. I can recommend django-registration (https://django-registration.readthedocs.io) application. It does require some custom template, but can save a lot of trouble with writing your own sign up views.
In my django application the form never returns true even if I add the same data as in the admin application. My model.py looks like:
from django.db import models
from django.db.models import ImageField, signals
from django.dispatch import dispatcher
from django.forms import ModelForm
# Create your models here.
class Image(models.Model):
emailAddress = models.EmailField(max_length=75)
image = ImageField(upload_to='photos')
caption = models.CharField(max_length=100)
class UploadForm(ModelForm):
class Meta:
model = Image
My views.py looks like:
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from competition.models import Image, UploadForm
# Create your views here.
def index(request):
images = Image.objects.all().order_by('emailAddress')
return render_to_response('images/index.html', {'images': images})
def uploadImage(request):
if request.method == 'POST': # If the form has been submitted...
form = UploadForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
emailAddress = form.cleaned_data['emailAddress']
image = form.cleaned_data['image']
caption = form.cleaned_data['caption']
i = Image(emailAddress=emailAddress, image = image, caption = caption)
i.save()
return HttpResponseRedirect('../image/')
else:
return render_to_response('images/upload.html', {'form': form})
else:
form = UploadForm() # An unbound form
return render_to_response('images/upload.html', {'form': form})
My template looks like:
<html>
<body>
<form enctype="multipart/form-data" action="/image/uploadImage" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</body>
</html>
I can get it work correctly if I use the admin application but need a generic form and this does't work as it keeps asking for a either the email address or image (the error appears above the image field). So why might my form not be valid?
You need to instantiate your form with request.FILES as well as request.POST.
As an aside, you can save the model form instead of creating the Image by hand in the view.
You have a required image but you aren't binding the file data to the form.
form = UploadForm(request.POST)
should be
form = UploadForm(request.POST, request.FILES)
See https://docs.djangoproject.com/en/1.3/ref/forms/api/#binding-uploaded-files
FileField and ImageField fields have two places need to notice:
Require enctype="multipart/form-data" in form element.
<form enctype="multipart/form-data" method="post" action="/foo/">
Require request.FILES for form constructor.
form = UploadFileForm(request.POST, request.FILES)
Please refer:
https://docs.djangoproject.com/en/2.2/topics/http/file-uploads/
https://docs.djangoproject.com/en/2.2/ref/forms/api/#binding-uploaded-files