Model Form not displaying - python

I am using modelform for a model department is not working. (BTW,I have a custom user model also in users app of same project). All I am getting is a 'Test up' button in the html output. Also, Change E-mail and Signout are displaying may be consequence to usage of allauth in middleware. I don't know whether allauth is interfering with this or not (hope not).I have added department model to admin but there is some strange thing appearing in admin described below
I have tried to debug with many ways.
Here is the model
from django.db import models
from django.conf import settings
from users.models import User,UserProfile
# Create your models here.
class department(models.Model):
Dept_CHOICES = (
(1, 'Inventory'),
(2, 'Dispatch'),
)
dept_type = models.PositiveSmallIntegerField(choices=Dept_CHOICES,default=1,unique=False),
HOD = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,),
Invest = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,),
def __str__(self):
return self.dept_type
Here is the view code
def add_model(request):
if request.method == "POST":
form = departForm(request.POST)
if form.is_valid():
model_instance = form.save(commit=False)
model_instance.save()
return redirect('/')
else:
form = departForm()
return render(request, "test.html", {'form': form})
base.html
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<main>
{% block content %}
{% endblock %}
</main>
</body>
</html>
test.html
{% extends 'base.html' %}
{% block content %}
<div class = "container">
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Test up</button>
</form>
</div>
{% endblock %}
admin.py
from core1.models import department
# Register your models here.
#admin.register(department)
class DepartmentAdmin(admin.ModelAdmin):
pass
output in admin of the site is a single field with strange name of
<django.db.models.fields.PositiveSmallIntegerField>
For additional info, I am using class view and function view in the same views.py file. Hope it is allowed.
I expect the form to be displayed
Tried form.as_p but getting
<<bound method BaseForm.as_p of <departForm bound=False, valid=False, fields=()>>
Tried form.valid
<bound method BaseForm.is_valid of <departForm bound=False, valid=False, fields=()>>

Solved on my own !
I checked Admin site. There is no department model displaying. This means either I am not migrating properly or my department model has an issue
My department model has all fields ending with a , (comma). Same removed and made the model more robust and without error.
Removed all migrations and done fresh migrate
Modified Admin as follows
# Register your models here.
class departmentadmin(admin.ModelAdmin):
fields = ['HOD', 'Investigator', 'dept_type']
list_display = ('HOD','Investigator','dept_type')
pass
admin.site.register(department, departmentadmin)
Now admin also displaying dpartment and form also displaying departments with required out put..

Related

Django 3: is_valid() is always false using FileField and FloatField

I am trying to make a simple form in Django that accepts some file upload fields and a few float fields. However, when I run this in my browser, the is_valid() never gets triggered even when all forms are filled in. I have looked through the Django docs and have tried to recreate the examples as much as possible, but I can't figure out what is wrong. I know that the is_valid() is not true because the page does not redirect to another page when submit is pressed. Also, if I go into the admin page, no instances of MyModel are made.
Here is my code.
models.py:
from django.db import models
# Create your models here.
class MyModel(models.Model):
file1 = models.FileField()
file2 = models.FileField()
x = models.FloatField()
y = models.FloatField()
z = models.FloatField()
def __str__(self):
return self.file1
forms.py:
from django import forms
from django.forms import ModelForm
from .models import MyModel
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
fields = '__all__'
views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect
from .forms import MyForm
# Create your views here.
def index_view(request):
if request.method == 'POST':
form = MyForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('some_page')
else:
form = DocumentsForm()
return render(request, 'index.html', {'form':form})
index.html:
<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Home Page!</h1>
<form method="POST" action="/">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="Submit">
</form>
</body>
</html>
My guess is it has to do with the fact that you haven't included enctype="multipart/form-data" in your <form> declaration in the HTML. It should look like this:
<form action="/" method="post" enctype="multipart/form-data" class="">
The multipart/form-data is necessary when uploading a file through forms.
Since you are sending both data and files, you need to specify the encoding of the form to:
<form enctype="multipart/form-data" method="POST" action="/">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="Submit">
</form>

Django form is not valid but no error is sent

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 - How do you get the corresponding model object in a for loop in html?

I am trying to create a simple django website where any user can rate and create posts. As displayed in this django tutorial (https://docs.djangoproject.com/en/1.7/topics/templates/), you can display all the model objects in html using a for loop. In my case, each object is going to be displayed with a Like and a Dislike button, so people can rate the post. My problem is: How do I know which object belongs to which like/dislike button so that the corresponding model field can be changed for that particular object? Thank You for answers!
models.py
from django.db import models
# Create your models here.
class Post(models.Model):
post_text = models.CharField(max_length=500)
pub_date = models.DateTimeField("date published")
likes = models.IntegerField(default=0)
dislikes = models.IntegerField(default=0)
def __str__(self):
return self.post_text
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AllPosts</title>
</head>
<body>
{% if post_list %}
<ul>
{% for post in post_list %}
<li>{{post.post_text}}</li>
<p>This post has {{post.likes}} likes and {{post.dislikes}} dislikes.</p>
<br>Leave a <button type="button" method="LIKE">Like</button> or a <button type="button" method="DISLIKE">Dislike</button>!</p>
{% endfor %}
</ul>
<h2>If you want to create a post yourself, click here.</h2>
{% else %}
<h1>There are no posts yet...</h1>
{% endif %}
</body>
</html>
views.py
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.utils import timezone
from .models import Post
# Create your views here.
def index(request):
post_list = Post.objects.order_by('-pub_date')
template = loader.get_template('post/index.html')
context = {'post_list': post_list, }
#if request.method == "LIKE":
# post = Post.objects.get(id=) How do I find out the id?
# return HttpResponse(template.render(context, request))
#else:
return HttpResponse(template.render(context, request))
def create(request):
template = 'post/create.html'
if request.method == 'POST':
post = Post()
post.post_text = request.POST.get("post_text")
post.pub_date = timezone.now()
post.save()
return render(request, template)
else:
return render(request, template)
In order for the buttons to work, they need to be inside a form element and be of type="submit" otherwise they won't do anything when clicked. To identify which button was clicked, you can then replace the method attributes with name="like" and name="dislike". The buttons can then be referenced to the related post by setting their value to the post ID.
Below is an example of the code that should do this. I've clipped out some of the unrelated parts of the code. (Note: I haven't tested this, so it may not work perfectly)
index.html UL element:
<ul>
{% for post in post_list %}
<li>
<span>{{post.post_text}}</span><br>
<p>This post has {{post.likes}} likes and {{post.dislikes}} dislikes.</p>
<form method="post">
<p>
Leave a <button type="submit" name="like" value="{{post.id}}">Like</button>
or a <button type="submit" name="dislike" value="{{post.id}}">Dislike</button>!
</p>
</form>
</li>
{% endfor %}
</ul>
views.py index:
def index(request):
if request.method == 'POST':
like = request.POST.get('like')
dislike = request.POST.get('dislike')
if like:
# Handle liked post
# `like` is equal to the post ID
else if dislike:
# Handle disliked post
# `dislike` is equal to the post ID
else:
# No action requested
else:
post_list = Post.objects.order_by('-pub_date')
template = loader.get_template('post/index.html')
context = {'post_list': post_list, }
return HttpResponse(template.render(context, request))
I hope this helps :)

Having trouble with Django forms "OperationalError: no such table" error

I'm trying to set up a form on Django that displays inputs on the page, but I get this error.
django.db.utils.OperationalError: no such table: firstapp_post
This doesn't happen right away, but when I try to use the submit feature on my form.
Right now this is what I have as my models:
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
post = models.CharField(max_length=500)
user = models.ForeignKey(User)
These are currently my forms:
from django import forms
from firstapp.models import Post
class IndexForm(forms.ModelForm):
post = forms.CharField()
class Meta:
model = Post
fields = ('post',)
This is my views file:
from django.shortcuts import render, redirect
from firstapp.forms import IndexForm
from django.views.generic import TemplateView
class HomePage(TemplateView):
template_name = 'home/home.html'
def get(self, request):
form = IndexForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = IndexForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
text = form.cleaned_data['post']
form = IndexForm()
return redirect('home:home')
args = {'form': form, 'text': text}
return render(request, self.template_name, args)
This is my base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Assignment 4</title>
<link rel='stylesheet' href='{% static "css/base.css" %}'/>
</head>
<body>
<p>{{ variable }}</p>
{% block body %}{% endblock %}
<script src= '{% static "js/base.js" %}'></script>
</body>
</html>
and my home.html:
{% extends 'base.html' %}
{% block body %}
<div class="container">
<p>Home</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
<p>{{ text }}</p>
</div>
{% endblock %}
Does anyone have any idea what this error even means or why I'm getting it? This has been driving me nuts. Thanks for the help!
As the error message mentions, that particular table does not exist in your database.
You can run the following command:
python manage.py makemigrations appname
By running makemigrations, you’re telling Django that you’ve made some changes to your models and that you’d like the changes to be stored as a migration.
Now run migrate again to create those model tables in your database
python manage.py migrate
Further Reading

Rendering/Raising A Validation Error on an HTML Template in Django

I'm attempting to list a validation error on my HTML template if the form on that template isn't properly submitted. My forms.py file includes a function (clean_email) that will catch any string that's entered that doesn't include an "#" symbol, and it actually works. Therefore, any form that I attempt to submit without an "#" character in the email field won't be submitted.
Unfortunately, the error isn't displayed as it should be on my HTML template. The code for displaying it is in line 15 of contact.html (contactform.errors ). This code doesn't produce any results. Here are the relevant files:
Models.py
from __future__ import unicode_literals
from django.db import models
class Contact(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
phone_number = models.CharField(max_length=30, blank=True)
email = models.CharField(max_length=50)
message = models.TextField(default=" ")
Forms.py
from models import Contact
from django.forms import ModelForm
from django.core.exceptions import ValidationError
from django import forms
class ContactForm(ModelForm):
class Meta:
model = Contact
fields = "__all__"
def clean_email(self):
email = self.cleaned_data["email"]
if "#" not in email:
raise ValidationError("Not an Email Address")
return email
Views.py
from django.shortcuts import render
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from forms import ContactForm
def contact(request):
contactform = ContactForm()
if request.method == "POST":
contactform = ContactForm(request.POST)
if contactform.is_valid():
message = contactform.save(commit=False)
message.save()
return HttpResponseRedirect(reverse("contact"))
else:
print(contactform.errors)
contactform = ContactForm()
return render(request,"contact_form/contact.html",{"contactform":contactform})
Finally, Contact.HTML
{% block content %}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="{% static "css/main.css" %}">
<link rel="stylesheet" href="{% static "css/contact.css" %}">
<div class="outer">
<form method="POST" action="">
{% csrf_token %}
<ul>
<li>
<label = for="email">Email</label>
{{ contactform.email }}
{{ contactform.errors }}
</li>
</ul>
<input type="submit" value="Submit Form"/>
</form>
</div>
{% endblock %}
Any ideas/help is appreciated, thanks!
Apart from using models.EmailField (which you should be doing) you need to change {{ contactform.errors }} to {{ contactform.email.errors }}
I figured it out. Before the validation error could even be raised, I was attempting to generate a brand new form.
contactform = ContactForm()
^That code in my views.py file would make it so an entirely new form was created on my HTML template. Once I got rid of it, everything worked like it should.

Categories

Resources