I'm a Django beginner and i have a little problem. I made a form for create the model FantaSquadra, and this works. Then I made a form to edit the model and when I press the submit button it doesn't do anything.
Can someone help me?
urls.py:
path('add/fantasquadra/', views.addFantaSquadra, name='creazione_fanta'),
path('edit/fantasquadra/<int:fantasquadra_id>/', views.editFantaSquadra, name='edit_fanta'),
views.py:
def addFantaSquadra(request):
elenco_fantasquadre = FantaSquadra.objects.all()
if request.method == "POST":
form = NewFantaSquadraForm(request.POST)
if form.is_valid():
fanta_item=form.save(commit=False)
fanta_item.save()
else:
form = NewFantaSquadraForm()
return render(request, 'sondaggio/fantasquadre.html', {'form': form})
def editFantaSquadra(request, fantasquadra_id):
item = get_object_or_404(FantaSquadra, pk=fantasquadra_id)
form = NewFantaSquadraForm(request.POST or None, instance=item)
elenco_fantasquadre = FantaSquadra.objects.all()
if form.is_valid():
form.save()
return render(request, 'sondaggio/fantasquadre.html', {'form': form})
forms.py:
class NewFantaSquadraForm(forms.ModelForm):
class Meta:
model = FantaSquadra
fields = ['nome_fantasquadra','proprietario']
fantasquadre.html
<html>
<h1>Scrivi il nome della tua fantasquadra</h1>
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
</html>
You have a link inside your button, for some reason. The link is taking priority over the button submission, so the data is never actually posted to the view.
Remove that <a> element.
Related
I am trying to create a user profiles for users in my Django app. I have the form displaying where I want it to and when I try to submit, nothing happens.
I put a print statement after the form.is_valid in my view.py and found that it wasn't 'valid' but I have no idea why.
I have tried several different ways to 'clean' / 'validate' data but I can't get past the form being 'invalid.'
Any help would be greatly appreciated!
urls:
path('userinfo/', views.user_info, name='userinfo')
form template:
{% extends "base.html" %}
{% load bootstrap4 %}
{% block content %}
<div class="container">
<h1>Enter User Info</h1>
<form method="POST" class="form">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-primary" value="Create Profile">
</form>
</div>
{% endblock %}
view:
def user_info(request):
form = ProfileForm()
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
form.save()
else:
form = ProfileForm()
return render(request, 'miraDashboard/form.html', context={'form': form})
model:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
name = models.CharField("Full Name", max_length=1024)
job_role = models.CharField("Role", max_length=254, default="Seeking Job Opportunities")
zip_code = models.CharField("Zip Code", max_length=5)
user_image = models.ImageField("Upload Profile Picture", upload_to='images/')
def __str__(self):
return f'{self.user.username} Profile'
form:
from django.forms import ModelForm
from .models import Profile
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = ['name','job_role','zip_code', 'user_image']
if you want to see errors in form change else statmant:
def user_info(request):
form = ProfileForm()
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
form.save()
else:
print(form.errors.as_data()) # here you print errors to terminal
return render(request, 'miraDashboard/form.html', context={'form': form})
after form.is_valid() you don't need to set it again (form = ProfileForm() in else statment). this way your form will get errors( you cen see them in form.errors).
I currently have a model that is called services, shown here...
class Services(models.Model):
service_sku = models.AutoField(primary_key=True)
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
forms.py
class ServiceForm(forms.ModelForm):
class Meta:
model = Services
fields = '__all__'
Based on the code shown above, I have two views, one will create instances of the model above and the other view will update the instance, as follows
def NewServices(request):
form = ServiceForm()
if request.method == 'POST':
form = ServiceForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('/')
return render(request, 'accounts/new_services.html', {'form': form})
def EditServices(request,pk):
service = Services.objects.get(service_sku=pk)
form = ServiceForm(instance=service)
if request.method == 'POST':
form = ServiceForm(request.POST, instance=service)
if form.is_valid():
form.save()
return redirect('/')
context = {'form':form}
return render(request, 'accounts/edit_services.html',context)
Template as follows
<div class="row">
<div class="col-md-7">
<div class="card card-body">
<form action="" method="POST">
{% csrf_token %}
{{form}}
<hr>
<input type="submit" name="Update">
</form>
</div>
</div>
</div>
Is it possible to show a readyonly of the service_sku within in my template form, when a instance needs to be updated and when a service_sku readonly is shown to be autogenerated in a template when creating a instance?
Yes. You can include the field in a form, so likely you should make a separate one to update:
class ServiceEditForm(forms.ModelForm):
service_sku = forms.IntegerField(disabled=True)
class Meta:
model = Services
fields = ('service_sku', 'name', 'price')
In the form you then simply use that new form:
def EditServices(request,pk):
service = Services.objects.get(service_sku=pk)
if request.method == 'POST':
form = ServiceEditForm(request.POST, request.FILES, instance=service)
if form.is_valid():
form.save()
return redirect('/')
else:
form = ServiceEditForm(instance=service)
context = {'form':form}
return render(request, 'accounts/edit_services.html', context)
Using disabled=True [Django-doc] does not only make sure the field is disabled at the client side, but it will also prevent a person to make a malicious POST request.
I have a simple form in Django, and in my template I want to display each individual object for the whole queryset which I am saving the form to. The error I am getting is that my form does not seem to submit on the first attempt. Only when I click the submit button, manually refresh the page and then 'confirm form resubmission' do I see my updated queryset objects displayed in the template.
I am saving my form like this in my views:
exercise_name = ExerciseName.objects.all()
if request.method == 'POST':
form = ExerciseNameForm(request.POST)
if form.is_valid():
form.save(commit=True)
else:
form = ExerciseNameForm()
and passing the queryset to the template through the following context:
{ 'exercise_name': exercise_name }
and iterating through it like
{% for exercise_title in exercise_name %}
#content displaying each iteration
{% endfor %}
with my form to update it like:
<div>
<form method = "POST">{% csrf_token %}
{{form.as_p}}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
I am not sure why it is making me refresh the page and resubmit the form again in order to see the updated queryset after submitting the form?
You should be doing something like this:
if request.method == 'POST':
form = ExerciseNameForm(request.POST)
if form.is_valid():
form.save(commit=True)
return HttpResponse("data submitted successfully")
else:
return render(request, "your_template.html", {'form':form})
else:
form = ExerciseNameForm()
return render(request, "your_template.html", {'form':form})
I have been going through the Django forms 'tutorial'. Once I had read through the tutorial, I tried modifying it to suit my needs and customize it to learn it Django forms well. I discovered whenever I modified the form, the website would not update. I assume its an error with my code, but I have not been able to find it.
# views.py
def contact(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 = ContactForm(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('/message_recived/')
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label='Name', max_length=100)
email = forms.EmailField(label='Email', max_length=100)
message = forms.CharField(label='Message', max_length=500)
# models.py
from django.db import models
class Contact(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
message = models.CharField(max_length=500)
and here is the contact.html template:
#contact.html
{% extends "BlogHome/headerAndFooter.html" %}
{% block content %}
<script>
document.title = "Pike Dzurny - Contact"
</script>
<form action="/message_recived/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
{% endblock %}
Did I do something wrong? I have tried clearing my browsers cache, using a new browser, and obviously refreshing it.
Looks like your forget to render response inside your view.
Also you need to include form into context to render template right.
Try to change view as follow:
def contact(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 = ContactForm(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('/message_recived/')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
# models.py
class Profile(models.Model):
name = models.CharField(max_length=255)
image = models.ImageField(upload_to=image_path, blank=True, null=True)
# forms.py
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
# views.py
def profile(request, id):
p = get_object_or_404(Profile, pk=id)
profile_form = ProfileForm(request.POST or None,
files=request.FILES or None,
instance=p)
if request.method == 'POST':
if profile_form.is_valid():
profile_form.save()
return render(request, 'profile.html', {'form': profile_form})
#profile.html
<form method="post" action="" enctype="multipart/form-data" >
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
If a user GETs /profile/1 and 1 exists, they get the form prefilled with all the values, including the image (if any)
If the user then POSTs updates to any of the fields except the image (clearing or changing), The page renders correctly after the update.
However, if the user changes the Image (clear or change), the change is not reflected in the rendered result: The image is always shown as empty. a quick GET solves the situation and displays the changed situation.
Does anyone know why the image field doesn't show the update in this situation?
Don't you have to do some sort of redirection to somewhere(obviously with a GET) when the profile form is successfully saved? You were always returning render.... and if you are having a POST request the form is going to stay with the POST data. So it should be:
# views.py
def profile(request, id):
p = get_object_or_404(Profile, pk=id)
profile_form = ProfileForm(request.POST or None, files=request.FILES or None, instance=q)
if request.method == 'POST':
if profile_form.is_valid():
profile_form.save()
# do the GET request to some page
return redirect('some-view-name', foo='bar')
return render(request, 'profile.html', {'form': profile_form})