I created a model form with a few fields and would like to save the data when a user enters values into the template and clicks submit.
However when I click 'submit' the values are not cleared from the form, and the data is not getting saved into the sqlite3 database which I checked using select * from notes_note;
I am not getting any error, it simply isn't saving that data.
Models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Note(models.Model):
owner = models.ForeignKey(User, on_delete=models.DO_NOTHING,)
title = models.CharField(max_length=100)
text = models.CharField(max_length=500)
createTime = models.DateTimeField()
from django.forms import ModelForm
class NoteForm(ModelForm):
class Meta:
model = Note
#fields = '__all__'
#fields = ['title', 'text', 'createTime']
exclude = ['owner']
Template
Log Out
<h2>Dashboard {{ user }}</h2>
<table>
<tr>
<td>
<form_name="noteForm" action="/notes/dashboard/" method="post"> {% csrf_token %}
{{ form.as_p }}
<input type= "submit" value="New Note"/>
</form>
</td>
</tr>
</table>
Views.py
#login_required(login_url="/notes/index/")
def dashboard(request):
if request.method == 'POST':
# d dict is a copy of our request.Post because it's immutable and we need to add owner
d = request.POST.copy()
d.update({'owner': request.user.id})
form = NoteForm(d)
if not form.is_valid():
template = loader.get_template('dashboard.html')
context = {
'form': form,
}
return HttpResponse(template.render(context, request=request))
# save the note to the database
# if the form is valid
note = form.save()
note.owner = request.user
note.save()
return redirect("dashboard")
else:
print("this prints out")
template = loader.get_template('dashboard.html')
context = {
'form': NoteForm(),
}
return HttpResponse(template.render(context, request=request))
I checked using a print statement in my dashboard function in views.py to see what is being processed, and it is hitting the else portion.
Related
I am new in Django but know some stuff and still need your help.
I want when a user submits a button after putting info in the search area to redirect to another page and accept data for future use.
What I did so far:
in models.py
from django.db import models
from django.contrib import auth
class Child(models.Model):
name = models.CharField(max_length=150, blank=True)
in forms.py
from django import forms
from .models import Child
class ChildlForm(forms.ModelForm):
class Meta:
model = Child
fields = ('name',)
in views.py
from django.shortcuts import render
import numpy as np
import pandas as pd
def home(request):
form = ChildForm()
if request.method == "POST":
form = ChildForm(request.POST)
if form.is_valid():
data = form.save(commit=True)
else:
return 'main/test.html'
return render(request,'main/index2.html',{'name':data.name})
return render(request,'main/index.html',{'form':form})
'test.html' is where the form is required to be filled by user. I want after the inform submitted the data is saved and then redirected to garden.html file.
the test.html file
<form method="POST">
{{ form }}
{% csrf_token %}
<input class="form-control mr-sm-2" type="text">
<button type="submit">OK</button>
</form>
the form is search ready template posted by bootstrap.
Could you please help to link successfully the files and get the data (name) to further use in garden.html?
In index2.html
{% extends "base.html" %}{% block content %}
{{b}}
{% endblock content %}
def home(request):
form = ChildForm()
if request.method == "POST":
form = ChildForm(request.POST)
if form.is_valid():
data = form.save(commit=True)
name=data.name
symbols = [name]
yahoo_financials = YahooFinancials(symbols)
new_data = pd.DataFrame()
for s in symbols :
new_data[s] = wb.DataReader(s, data_source ='yahoo', start = '2014-1-1')['Adj Close']
a = new_data[s]
b = a[-1]
context={
'name':name,
'b':b
}
else:
form = ChildForm()
return render(request,'test.html',{'form':form})
return render(request,'garden.html',context)
return render(request,'test.html',{'form':form})
besides there is a typo in your code
class ChildlForm(forms.ModelForm):
In my app, I have Users create Post objects. Each Post has a User
class Post(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE)
...
I want to create a post-submission form for editing and submission, so I plan to use Django's ModelForm functionality.
class PostForm(ModelForm):
class Meta:
model = Post
fields = "__all__"
However, if I do this, then whoever is viewing the form will be able to set who the Post author is. I want to make sure that the resulting user field is them. But, if I exclude the user field from the ModelForm,
class PostForm(ModelForm):
class Meta:
model = Post
exclude = 'user'
then the user will not be set on form submission. I've hacked my way around this by making a custom form and updating the post field
def submit_view(request):
....
request.POST = request.POST.copy()
request.POST.update({
'user' : request.user.id
})
form = PostForm(request.POST, request.FILES)
....
but then I lose automatic UI generation and form validation, which in some ways defeats the purpose of the Form class. Could somebody point me to the idiomatic way of setting the user field without including it in the Form?
Try this view:
def submit_view(request):
form = PostForm(request.POST or None)
if form.is_valid():
new_post = form.save(commit=False)
new_post.user = request.user
new_post.save()
view.py
from django.views.generic import CreateView
from .models import Post
class PostCreate(CreateView):
model = Post
template_name ="new_Post_form.html"
fields = ['text']
def form_valid(self, form):
object = form.save(commit=False)
object.user = self.request.user
object.save()
return super(PostCreate, self).form_valid(form)
def get_success_url(self):
return "/"
url.py
url(r'^newpost$',views.PostCreate.as_view(),name='post_new',),
new_post_form.html
<form method="post" enctype="multipart/form-data" class="form" action="newpost" id="new-post-form">
<div class="modal-body">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</div>
I am trying to have a user input a task from the frontend and have that data instantiate a new model and add this new field in the database associated with their account. I have tried the following;
Profile HTML
<form id="taskitem_form" method="post" action="/">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>
Model
class TaskItem(models.Model):
taskn = models.CharField(max_length = 400)
usern = models.ForeignKey(User)
def __str__(self):
return self.taskn
Views
def add_task(request):
# Get the context from the request.
#context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = TaskItemForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
task = form.save(commit=False)
task.usern = request.user
task.save()
# we should redirect after data modifying
return redirect('/user/%s' %(request.user))
else:
# If the request was not a POST, display the form to enter details.
return render(request, 'profile.html', {'form': form})
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'profile.html', {'form': form})
Forms
from django import forms
from bkmks.models import TaskItem
class TaskItemForm(forms.ModelForm):
taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")
# An inline class to provide additional information on the form.
class Meta:
fields = ('taskn', 'usern' )
#This is the association between the model and the model form
model = TaskItem
Lot's of Changes needed to your code.
I'm posting a working version so that you can try.
Put profile.html file as bkmks/templates/bkmks/profile.html
Get it working. Customize later.
profile.html
<form id="taskitem_form" method="post" action="">
{% csrf_token %}
{{form}}
<input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>
model as it is.
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render_to_response, RequestContext, redirect
from .forms import TaskItemForm
#login_required
def add_task(request):
# Get the context from the request.
context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = TaskItemForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
task = form.save(commit=False)
task.usern = request.user
task.save()
# Redirect to home (/)
return redirect('/')
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = TaskItemForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render_to_response('bkmks/profile.html', {'form': form}, context)
forms.py
class TaskItemForm(forms.ModelForm):
# task is changed to taskn
taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")
# An inline class to provide additional information on the form.
class Meta:
fields = ('taskn',)
#This is the association between the model and the model form
model = TaskItem
If you get any error or data is not getting saved post here.
Going through Django tutorial will be an wise decision.
The below should do what you need. You really want to inherit 100% of everything from your model when you can. This insures all model validation trickles down to the form. I utilized verbose_name and help_text on the model to achieve this.
Models
from django.conf import settings
class TaskItem(models.Model):
taskn = models.CharField(
max_length=400,
verbose_name="task",
help_text="Please enter your task.",
)
usern = models.ForeignKey(
to=settings.AUTH_USER_MODEL,
related_name="tasks",
)
def __str__(self):
return self.taskn
For the forms, I have added a forms.HiddenInput widget to the user, assuming you want the user submitting the task to become the user.
Forms
from django import forms
from bkmks.models import TaskItem
class TaskItemForm(forms.ModelForm):
widgets = {
'user': forms.HiddenInput,
}
class Meta:
model = TaskItem
fields = ('taskn', 'usern')
I have used a CreateView to reduce code complexity, and overrode the form_valid to add the user instance to the form.
Views
from django.views.generic import CreateView
from bkmks.models import TaskItem
from bkmks.forms import TaskItemForm
class TaskCreateView(CreateView):
model = TaskItem
form_class = TaskItemForm
template_name = "path/to/template.html"
def form_valid(self, form):
form.instance.user = self.request.user
return super(TaskCreateView, self).form_valid(form)
Finally, in the template, we simply want to use {{ form }}. I see you are looking into bootstrap. I'll suggest django-crispy-forms for this, but that is beyond the scope of your question.
Template
<form id="taskitem_form" method="post" action="/">
{% csrf_token %}
{{ form }}
<input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>
https://docs.djangoproject.com/en/1.8/topics/http/shortcuts/#render-to-response
render_to_response expects a template as the first argument, not a url.
I think in your second call to render_to_response should include the template name / path , while the first one should use a return HttpResponseRedirect("/") instead, though its not clear exactly what your problem is.
Add this line to imports in views.py
from django.contrib.auth.decorators import login_required
Decorate add_task view
#login_required
def add_task(request):
Then, edit part of your code
if form.is_valid():
task = form.save(commit=False)
task.usern = request.user
task.save()
# we should redirect after data modifying
return redirect('/')
else:
# etc.
Some notes. You may replace render_to_response to render.
Remove this line
context = RequestContext(request)
Replace
# Wrong usage, actually.
# Should be something like
# render_to_response(template_name, context, context_instance)
render_to_respone('/', {'form': form}, context)
with
# if template_name is "profile.html"
render(request, 'profile.html', {'form': form})
Why define a field called task in the form if you've already got a field in the model called taskn, wouldn't it be better to just use that? And like the guys have said, you need to specify a template to render (that's why you're not seeing anything).
It'd also be a good idea to pass the current user to the form's user field.
#login_required
def add_task(request):
# Get the context from the request.
context = {}
# A HTTP POST?
if request.method == 'POST':
form = TaskItemForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save()
# Now call the index() view.
# The user will be shown the homepage.
return render_to_response(
'profile.html',
{'form': form},
RequestContext(request, context)
)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = TaskItemForm(initial={'usern': request.user})
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render_to_response(
'profile.html',
{'form': form},
RequestContext(
request, context
)
)
Form;
from django import forms
from bkmks.models import TaskItem
class TaskItemForm(forms.ModelForm):
taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")
# An inline class to provide additional information on the form.
class Meta:
fields = ('taskn', 'usern' )
#This is the association between the model and the model form
model = TaskItem
I'm trying to add a new feature to my existing app that let users create a profile and upload a pictures of their pets.
When a user login , he gets redirected into the profile which display his name and also he can add a picture of himself into the model which will get displayed on the profile page.
At the moment , I can retrieve the name into the template but I can't seem to display the user's name and upload picture at the same time.
Whenever I click Add picture , It doesn't let the user upload a picture instead I get this error
'PictureForm' object has no attribute 'save'
pet = form.save(commit =False) ...
I could design the page to let the user upload a picture but not display the name at the same time.
I think the problem lays in my profile.html and Profile function at views.py
Parts of my views.py
#login_required
def Profile(request):
Person = request.user.get_profile()
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
if request.method == "POST":
form = PictureForm(request.POST ,request.FILE or None)
if form.is_valid():
pet = form.save(commit =False)
pet.save()
context = (
{'Person': Person} ,
{'form':PictureForm()}
)
return render_to_response('profile.html', context, context_instance=RequestContext(request))
Parts of my forms.py
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from pet.models import *
class PictureForm(forms.Form):
class Meta:
model = Person
fields = ('image')
My profile.html
{% if Person %}
<ul>
<li>Name : {{Person.name}} </li>
</ul>
{% endif %}
<form method="POST" enctype="multipart/form-data" "action" >
{% csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type = "submit" value= "Add Picture" />
</form>
My models.py
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
class Person(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
def __unicode__(self):
return self.name
class Pet(models.Model):
Person = models.ForeignKey(Person)
description = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
def __unicode__(self):
return self.description
PictureForm needs to inherit from forms.ModelForm, not forms.Form.
Erase your form.save(commit=False). You will only do that if you override your save method
#login_required
def Profile(request):
Person = request.user.get_profile()
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
if request.method == "POST":
form = PictureForm(request.POST ,request.FILES)
if form.is_valid():
form.save()
context = (
{'Person': Person} ,
{'form':PictureForm()}
)
return render_to_response('profile.html', context, context_instance=RequestContext(request))
UPDATE:
[.....]
board = Board.objects.get(board=picture.board)//remove this
the_id = board.id //remove this
return HttpResponseRedirect(reverse('world:Boat', kwargs={'animal_id': picture.board.id })) // change the_id into picture.board.id
You have a typo. It should be request.FILES.
no buddy. your problem is in your model.py:
just add this function to your model
def save(self,*args, **kw):
super(PictureForm,self).save(*args, **kw)
Why my form is not filled with data from model?
This is my model.py
class People(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=100)
address = models.CharField(max_length=255)
This is my forms.py
from django.forms import ModelForm
class EditForm(ModelForm):
class Meta:
model = People
exclude=('user',)
views.py
def edit_data(request):
user = request.user
people = People.objects.get(user=user)
form = EditForm(request.POST, instance = people)
if request.method == 'POST':
if form.is_valid():
form.save()
else:
print 'Error'
else:
form = EditForm()
return render_to_response('profile.html',{'form':form}, context_instance=RequestContext(request))
profile.html
<form action="/profile/" method="post">{% csrf_token %}
{{ form.as_p }}
</form>
The problem is that you're redefining form in your else clause (to a new instance of your EditForm, which doesn't have the instance variable set). Remove the else (and the line under it) and you should be good to go.