See the code below. I'm trying to use ModelForms to add records to a database, but it keeps returning the server error - seemingly against the .save() action, but I'm not quite sure. Any help towards how I can fix this would be really appreciated.
#view.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, render_to_response, get_object_or_404
from django.template import RequestContext
from forms import ContactForm, wallForm
from django.core.mail import send_mail
from home.models import wall
from django.forms import ModelForm
def wallpost(request):
if request.method == 'POST':
new_post = wallForm(request.POST)
if form.is_valid():
f = form.cleaned_data['postContent']
new_post.save()
return HttpResponseRedirect('/home/')
else:
form = wallForm()
return render(request, 'home/wall_post.html', {'form': form,})
#model.py
from django.db import models
class wall(models.Model):
clusterId = models.ForeignKey(cluster)
userId = models.ForeignKey(user)
postContent = models.CharField(max_length=800)
likes = models.IntegerField(default=0)
post_timestamp = models.DateTimeField('date published')
clusterId.blank = True
userId.blank = True
postContent.blank = True
likes.blank = True
post_timestamp.blank = True
#forms.py
from django import forms
from django.forms import ModelForm
from home.models import wall
class wallForm(ModelForm):
class Meta:
model = wall
#template.py
<h1>Posting test</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
<table>
{{ form.as_p }}
</table>
{% csrf_token %}
<input type="submit" value="Submit">
</form>
<b>Go back...</b>
Your problem is here:
def wallpost(request):
if request.method == 'POST':
new_post = wallForm(request.POST)
if form.is_valid():
f = form.cleaned_data['postContent']
new_post.save()
return HttpResponseRedirect('/home/')
else:
form = wallForm()
return render(request, 'home/wall_post.html', {'form': form,})
In this line if form.is_valid(), form is not actually defined. You probably want if new_post.is_valid(), and similarly form.cleaned_data should be new_post.cleaned_data.
Also, its not clear what you are doing with this line f = form.cleaned_data['postContent'], because you don't use f anywhere.
Thanks for your input. After setting debug = True, I realised that the error was coming from two different points.
Two of my foreign key fields in my model could not be empty (despite setting their model attribute blank = True). Once this was resolved, there was then an error in the database;
I'm not sure what caused the database error, but when I dropped the database, created a new one, and re-ran syncdb, everything seemed to work fine. Must have something to do with fields not lining up.
Thanks again for the help.
Related
The form I created is not inserting the data into my database table. As far as I can tell I've done everything correctly but it still refuses to do so instead it "post" in the console and clears the form fields without creating nothing in the database. None of the data that entered is saved anywhere? Here are the files below hopeful someone can see something I'm missing.
ps. I've connected my database, ran migrations and created a superuser as well but still nothing.
models.py
from django.db import models
Media_Choices = (
("TV", "TV"),
("Radio", "Radio"),
("Youtube", "Youtube"),
("Podcast", "Podcast"),
)
class Appear(models.Model):
Show = models.CharField(max_length=100)
Media = models.CharField(max_length=30, blank=True, null=True, choices=Media_Choices)
Episode = models.IntegerField()
Date = models.DateField(max_length=100)
Time = models.TimeField(auto_now=False, auto_now_add=False)
Producer = models.CharField(max_length=100)
Producer_Email = models.EmailField(max_length=254)
def __unicode__(self):
return self.Show + ' ' + self.Producer_Email
forms.py
from django import forms
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from .models import Appear
class AppsForm(ModelForm):
class Meta:
model = Appear
fields = '__all__'
def clean_Producer_Email(self):
Producer_Email = self.cleaned_data.get('Producer_Email')
if (Producer_Email == ""):
raise forms.ValidationError('field cannot be left empty')
for instance in Appear.objects.all():
if instance.Producer_Email == Producer_Email:
raise forms.ValidationError('Please fill in correct email')
return Producer_Email
views.py
from django.shortcuts import redirect, render
from django.http import HttpResponse
from .forms import AppsForm
from .models import Appear
def AppS(request):
if request == 'POST':
form = AppsForm(request.POST)
if form.is_valid():
Apps = form.save(Commit=False)
Apps.save()
else:
form = AppsForm()
return render(request, 'AppsForm.html', {'form': form})
def results(request):
return render(request, 'Results.html')
AppsForm.html
<body>
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
<form action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="submit">
</form>
{% endblock %}
enter code here
You might be missing form errors due to which the form is not saving. Try printing if there are any form errors.
if form.is_valid():
Apps = form.save(Commit=False)
Apps.save()
else:
print(form.errors)
So I have been trying to build a manager of activities with django and I'm still on the scratch. I was trying to test if the code can simply show if a acitivity is done or not, but it don't change anything. Everything looks good to me and I don't know if the error is in the form, in the view that saves the form or in anything else. I already tried to change the widget and fields of form and haven't been succeed in it.
models.py:
from django.db import models
from django.contrib.auth.models import User
class Activity(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=30)
is_complete = models.BooleanField()
def __str__(self):
return self.title
forms.py:
from .models import Activity
class ActivityUpdateForm(ModelForm):
class Meta:
model = Activity
fields = ['is_complete']
views.py:
from .models import Activity
from .forms import ActivityUpdateForm
def home(request):
acts = Activity.objects.all()
if request.method == 'POST':
form = ActivityUpdateForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('home')
else:
form = ActivityUpdateForm()
context = {
'acts': acts,
'form': form,
}
return render(request, 'diary/home.html', context)
template:
{% for act in acts %}
<form method="POST">
{% csrf_token %}
<p>{{ act.title }}</p>
<p>Is complete: {{ act.is_complete }}</p>
{{ form }}
<p>{{ act.author }}</p>
<button type="submit">Submit</button>
</form>
{% endfor %}```
This is not elegant, but you just might need to do this:
data = Activity.objects.get(author=request.user)
data.is_complete = form.cleaned_data["is_complete"]
data.save()
Please delete form.save() and write the code above.
i'm not sure if this works, but please give it a try.
I started to learn Django today, but I am stuck at using forms. I have created two forms: /contact and /blog-new. The form at the Contact page is working fine, but the one at /blog-new is redirecting me to the home page after the submission button is pressed and no information is printed in the terminal nor saved in the database.
Code on Github
I appreciate if someone can explain to me what I did wrong as I cannot figure it out. Thank you!
mysite/blog/forms.py
from django import forms
from .models import BlogPost
class BlogPostModelForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'slug', 'content']
mysite/blog/views.py
from .forms import BlogPostModelForm
def blog_post_create_view(request):
# create objects
# ? use a form
# request.user -> return something
form = BlogPostModelForm(request.POST or None)
if form.is_valid():
print(form.cleaned_data)
form.save()
form = BlogPostModelForm()
template_name = 'form.html'
context = {'form': form}
return render(request, template_name, context)
mysite/blog/models.py
from django.db import models
# Create your models here.
class BlogPost(models.Model):
title = models.TextField()
slug = models.SlugField(unique=True)
content = models.TextField(null=True, blank=True)
mysite/mysite/urls.py
from blog.views import (
blog_post_create_view,
)
urlpatterns = [
..
path('blog-new', blog_post_create_view),
..
]
mysite/templates/form.html
{% extends "base.html" %}
{% block content %}
{% if title %}
<h1>{{ title }}</h1>
{% endif %}
<form method='POST' action='.'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Send</button>
</form>
{% endblock %}
You need to point to right url in action attribute of form.
<form action="/blog-new/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
I think it's not necessary in your case but you could also refactor your view to match the docs.
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import SomeForm
def some_view(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 = SomeForm(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 = SomeForm()
return render(request, 'template_name.html', {'form': form})
You need to point to right url in action attribute of form.
That was not actually the solution but something that helped me to figure out what was wrong.
It is not necessary to point to /blog-new/ as . for action will point to the same page, but I have tried with /blog-new/ as action URL and I was surprised to see that /blog-new/ page doesn't exist.
The bug was in mysite/mysite/urls.py for missing a /:
path('blog-new', blog_post_create_view),
It is funny (and annoying) how a symbol like / missing from your code will mess up everything and make you spend hours trying to find a solution as simple as that.
Thank you for your time spend to have a look over my code and try to help me!
Django newb here, but I'm learning.
Problem Statement
Input fields not rendering in html template.
Output in Browser
True
| Submit Button |
Relevant Code
forms.py
from django import forms
from django.db import models
class PostNotes(forms.Form):
clientid = models.IntegerField()
notetext = models.CharField(max_length=1000)
-
views.py
def post_form_notes(request):
if request.method == 'GET':
sawit = True
form = PostNotes(initial={'notetext':'This is a sample note'})
else:
sawit = False
pass
return render(request, 'clientadmin/post_form_notes.html', {
'form': form,
'sawit': sawit,
})
-
post_form_notes.html
{{ sawit }}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Troubleshooting Already Done
I have backed out a fair amount of the code (specifically if I see a
POST) request from the browser. No change.
I have also included a variable to ensure I am seeing the GET request and also the template variables are working. I get output of True.
Simplified the Form Class as much as possible.
I modified the forms.py to use the model I already had for the DB.
forms.py:
from django.forms import ModelForm
from clientadmin.models import notes
class PostNotes(ModelForm):
class Meta:
model = notes
fields = ['notedate', 'notetext']
I also modified the views.py to not set an initial value, so the function uses the following instead of what was asked.
models.py:
def post_form_notes(request):
if request.method == 'GET':
form = PostNotes()
else:
pass
return render(request, 'clientadmin/post_form_notes.html', {
'form': form,
})
Hope this helps someone that was having the same problem I was...
Reference the following URL for further information: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/
I've only been at python for about 2 weeks now and I've run into an issue which I've been trying to figure out for the past 3 days. I've read through the official documentation and pretty much every tutorial and youtube video available.
I'm trying to build a simple blog as a first project and would like to have a section where people can post comments. I have set up the comments model and a modelform to go along with it. However, I can't figure out how to get django to create the form for me in the template, nothing is displayed.
models.py
from django.db import models
from django.forms import ModelForm
class posts(models.Model):
author = models.CharField(max_length = 30)
title = models.CharField(max_length = 100)
bodytext = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.title
class comment(models.Model):
timestamp = models.DateTimeField(auto_now_add=True)
author = models.CharField(max_length = 30)
body = models.TextField()
post_id = models.ForeignKey('posts')
def __unicode__(self):
return self.body
class commentform(ModelForm):
class Meta:
model = comment
views.py
from django.shortcuts import render_to_response
from blog.models import posts, comment, commentform
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
def home(request):
entries = posts.objects.all()
return render_to_response('index.html', {'posts' : entries})
def get_post(request, post_id):
post = posts.objects.get(id = post_id)
context = {'post': post}
return render_to_response('post.html', context)
def add_comment(request, post_id):
if request.method == 'POST':
form = commentform(request.POST)
if form.is_valid():
new_comment = form.save(commit = false)
new_comment.post_id = post_id
new_comment.save()
else:
form = commentform()
context = RequestContext(request, {
'form': form})
return render_to_response('post.html', context)
Urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'blog.views.home', name='home'),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^(?P<post_id>.*)/$', 'blog.views.get_post'),
url(r'^post_comment/(\d+)/$','blog.view.add_comment'),
post.html
{% extends 'base.html' %}
{% block content %}
<p><h3> {{ post }} </h3></p>
<p> {{ post.bodytext }} </p>
<br><br><br><br>
<form action="/post_comment/{{ post.id }}/" method="POST"> {% csrf_token %}
{{ form }}
<input type="submit" value="Post">
</form>
{% endblock %}
I do get a 403 error CSRF verification failed but, the more pressing issue I think is that the {{ form }} doesn't do anything in the template.
I believe home function and get_post function are working and all the urls are working properly. So, I assume there's something wrong with the add_comment function or in posts.html.
Thanks
Django isn't magic. Your comment form is in a completely different view from the one that displays the blog post. So how is Django supposed to know to render it? You need to actually pass the form object to the template somehow.
The way that this was done in the old contrib.comments app was to have a simple template tag which was responsible for just displaying the comment form for an object, which you could place on any template. The form itself submitted to its own view as usual.
One thing you might check is the syntax of the render_to_response call. I believe you'll want to define it like this. (Maybe your syntax will work too, and this isn't the issue, but I have mostly seen the call made like this). This could be the cause of the missing form in the context.
return render_to_response('post.html',
{'form': form},
context_instance=RequestContext(request))
Let me know if this works. Hope this helps,
Joe
Reference: https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#django.shortcuts.render_to_response