Not Null constrain failed Integrity Error - python

Hi I am having trouble figuring out how to solve this error. I was creating a form to be able to add new topics to a website I am working on. After creating the form and trying to use it to submit a request to add a new topic I got a integrityError which I haven't encountered before. After doing some research I know it has something to do with a foreign key relationship where there is a field that is empty inside the database but I am not sure how to root cause it.
here is my Models.py file:
from django.db import models
# Create your models here.
class Category(models.Model):
"""A category the user is writing about"""
text = models.CharField(max_length=200)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
"""Return a string represtation of the model."""
return self.text
class Topic(models.Model):
"""A topic that is associated with a certain Category"""
category = models.ForeignKey(Category, on_delete=models.CASCADE)
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Topics'
def __str__(self):
"""Return string represtation of the model."""
return self.text
class Entry(models.Model):
"""A entry associated with a certain topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Entries'
def __str__(self):
"""Return string represtation of the model."""
return self.text[:50] + "..."
forms.py
from django import forms
from .models import Category, Topic
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ['text']
labels = {'text': ''}
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from .models import Category, Entry, Topic
from .forms import CategoryForm, TopicForm
# Create your views here.
def index(request):
"""The home page for Learning Logs"""
return render(request, 'blogging_logs/index.html')
def categories(request):
"""show all categories"""
categories = Category.objects.all()
context = {'categories': categories}
return render(request, 'blogging_logs/categories.html', context)
def topics(request, category_id):
"""Show all topics for a single category"""
category = Category.objects.get(id=category_id) # get category that was requested
topics = category.topic_set.all() # get all topics associated with category that was requested
context = {'category': category, 'topics': topics}
return render(request, 'blogging_logs/category.html', context)
def topic(request, entry_id):
"""Show entry for single topic"""
topic = Topic.objects.get(id=entry_id)
entries = topic.entry_set.all()
context = {'topic': topic, 'entries': entries}
return render(request, 'blogging_logs/topic.html', context)
def new_category(request):
"""Add a new category"""
if request.method != 'POST':
# No data submitted; create a blank formself.
form = CategoryForm()
else:
# POST data submitted; process data
form = CategoryForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogging_logs:categories'))
context = {'form': form}
return render(request, 'blogging_logs/new_category.html', context)
def new_topic(request):
""" Add new topic to category """
if request.method != 'POST':
# No data submitted; create a blank formself.
form = TopicForm()
else:
form = TopicForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogging_logs:topics'))
context = {'form': form}
return render(request, 'blogging_logs/new_topic.html', context)
Any help to point me in the right direction is appreciated thank you!
Select Category
Add new topic to category

class Topic(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
#your other fields
Run python manage.py makemigrations and python manage.py migrate command, the error will be removed.

Related

Django TypeError: Field 'id' expected a number but got <homeworkForm bound=True, valid=Unknown, fields=(title;descripiton;due)>

I have been trying to allow staff users to post homework to a database however I keep running into the issue above. I've tried setting data['id'] = 0/'' as well as dropped the table and makemigrations/migrate.
models.py
from django.db import models
from teachers.models import Teacher
class Homework(models.Model):
title = models.CharField(max_length=100)
descripiton = models.CharField(max_length=500)
due = models.DateField()
teacher = models.OneToOneField(
Teacher, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
form.py
from django import forms
class DateInput(forms.DateInput):
input_type = 'date'
class HomeworkForm(forms.Form):
title = forms.CharField(label='Title', max_length=100)
descripiton = forms.CharField(label='Descripiton', max_length=500)
due = forms.DateField(label='Due', widget=DateInput)
views.py
def homework(request):
if request.user.is_authenticated & request.user.is_staff:
if request.method == 'POST':
data = request.POST.copy()
data['teacher'] = request.user.username
request.POST = data
print(request.POST)
form = HomeworkForm(request.POST)
if form.is_valid():
post = Homework(form)
post.save()
messages.info(request, 'Form sent')
print('worked')
return render(request, 'index/index.html')
else:
print('error in form')
form = HomeworkForm()
return render(request, 'dashboard/setHomework.html', {'form': form})
else:
form = HomeworkForm()
return render(request, 'dashboard/setHomework.html', {'form': form})
else:
return redirect('index')
Did you try data['teacher'] = request.user instead of data['teacher'] = request.user.username ?
You do not need to use request.POST.copy(), request.POST is already a dictionary.
I appreciate the answers. I managed to fix the issue by converting the form to a model form as that form model works better for the situation as the model fields are mapped directly to the inputs.
new forms.py
from homework.models import Homework
from django import forms
class HomeworkForm(forms.ModelForm):
class Meta:
model = Homework
fields = ['title', 'description', 'due']
widgets = {
'due': forms.DateInput(format=('%m/%d/%Y'), attrs={'label': 'due date', 'type': 'date'}),
}

Trying to link two models with a ForeignKey but get the error "IntegrityError NOT NULL"

I have a model where a user posts a job vacancy, then other users can submit applications. The submit application model is called 'CandidatesSubmission' & pulls the 'title' from a different app/model 'JobPosts'.
I can add submit applications through the ADMIN page fine, but when trying to do so with a form I get "IntegrityError NOT NULL constraint failed: candidates_candidatessubmission.title_id."
I believe that I'm missing something in my Views.py that essentially says "use the title of job vacancy as the title field.
I have tried adding null=True, blank=False but which stops the error but the title isn't saved to the database.
Any suggestions on what I'm doing wrong would be great. Thank you
models.py
class CandidatesSubmission(models.Model):
title = models.ForeignKey('jobs.JobsPost', on_delete=models.CASCADE)
Fee = models.CharField(max_length=50, null=False, blank=False)
CandidateFirstName = models.CharField(max_length=50, null=True, blank=False)
CandidateSecondName = models.CharField(max_length=50, null=True, blank=False)
created = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.db.models import Q
from django.http import HttpResponseNotFound
from jobs.models import JobsPost
from candidates.models import CandidatesSubmission
from candidates.forms import CreateCandidatePostForm
from account.models import Account
from operator import attrgetter
# Create your views here.
def submit_candidates_view(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
form = CreateCandidatePostForm(request.POST or None, request.FILES or None)
if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(email=user.email).first()
obj.author = author
obj.save()
form = CreateCandidatePostForm()
context['form'] = form
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, 'candidates/submit_candidates.html', context)
def response_view(request):
context = {}
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, "candidates/response.html", context)
forms.py
from django import forms
from candidates.models import CandidatesSubmission
class CreateCandidatePostForm(forms.ModelForm):
class Meta:
model = CandidatesSubmission
fields = ['Fee', 'CandidateFirstName', 'CandidateSecondName']
def save(self, commit=True):
submission_post = self.instance
submission_post.Fee = self.cleaned_data['Fee']
submission_post.CandidateFirstName = self.cleaned_data['CandidateFirstName']
submission_post.CandidateSecondName = self.cleaned_data['CandidateSecondName']
if commit:
submission_post.save()
return submission_post
if you have "current" title, so your slug might store it, so you can use it like that.
def submit_candidates_view(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
form = CreateCandidatePostForm(post_slug=slug, request.POST or None, request.FILES or None)
if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(email=user.email).first()
obj.author = author
obj.save()
form = CreateCandidatePostForm()
context['form'] = form
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, 'candidates/submit_candidates.html', context)
in your forms.py we replace __init__ method to receive slug of your title
class CreateCandidatePostForm(forms.ModelForm):
class Meta:
model = CandidatesSubmission
fields = ['Fee', 'CandidateFirstName', 'CandidateSecondName']
def __init__(self, *args, **kwargs):
self.post_slug = kwargs.pop("post_slug", None)
super().__init__(*args, **kwargs)
def save(self, commit=True):
submission_post = self.instance
submission_post.title = JobsPost.objects.get(slug=self.post_slug)
if commit:
submission_post.save()
return submission_post

Django pass time value and user value to forms.py

I have a model like this:
from django.db import models
from django.contrib.auth.models import User
class Task(models.Model):
title = models.CharField(max_length=200)
pub_date = models.DateTimeField(default)
completed = models.BooleanField(default=False)
description = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
def summary(self):
return self.description[:50]
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
def __str__(self):
return self.title
I have a forms.py like this because I don't want the user to be able to determine which user is saving the data and I want the pub_date to be the time now:
from django import forms
from .models import Task
from django.utils import timezone
class Taskform(forms.ModelForm):
class Meta:
model = Task
fields = ['title', 'description', 'completed']
My view is like this:
#login_required
def create(request):
form = Taskform(request.POST or None)
task = Task()
task.pub_date = timezone.datetime.now()
task.user = request.user
if form.is_valid():
form.save()
return redirect('')
return render(request, 'home/create.html', {'form': form})
I want to pass the time and the user to the form as it validates but I'm not sure how?
You can use form.save() with commit=True argument to take task instance and update it:
if form.is_valid():
task = form.save(commit=False)
task.pub_date = timezone.datetime.now()
task.user = request.user
task.save()
return redirect('')
Check detail here.

ImageField Form doesn't work in django

I know that there's a lot of similar questions to mine on stackoverflow but none of them fixed my problem.
I have a form with an imagefield which doesn't work as it should redirect to the index page when it succeeds but it doesn't. I can create a payment with that image from the admin panel but the form doesn't work.
models.py
class Payment(models.Model):
Address = models.CharField(max_length=255)
Payment_ID = models.ImageField(upload_to='payproof')
Status = models.CharField(max_length=5, default="X")
Review_result = models.CharField(max_length=255, default="Not yet reviewed")
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.Status
def __str__(self):
return self.Status
views.py
def new_payment(request):
template ='payment.html'
form = PayForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('index')
else:
form = PayForm()
context = {
'form' : form,
}
return render(request, template, context)
forms.py
class PayForm(forms.ModelForm):
Payment_ID = forms.ImageField()
class Meta:
model = Payment
fields = ['Address',
'Payment_ID']
So the problem was simple i was doing request.POST but the img is a file so all what i should of done was add request.FILES
form = PayForm(request.POST, request.FILES or None)

django unable to saved forms in database

I'm learning django and I'm trying to save the form using POST method and found its working fine, I'M not able to see the saved message in database(form is not submitted)
Models.py
class Post(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(max_length=10000)
pub_date = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=200, unique=True)
def __unicode__(self):
return self.title
def description_as_list(self):
return self.description.split('\n')
class Comment(models.Model):
title = models.ForeignKey(Post)
comments = models.CharField(max_length=200)
def __unicode__(self):
return '%s' % (self.title)
Forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'description')
editPostedForm = modelformset_factory(Post, PostForm)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('comments',)
exclude = ('title',)
Views.py
def detail(request, id):
posts = Post.objects.get(id=id)
comments = posts.comment_set.all()
forms = CommentForm
if request.method == 'POST':
form = CommentForm(request.POST, instance=posts)
print form
if form.is_valid():
form.save(commit=False)
form.save()
else:
print form.errors
else:
form = PostForm()
return render(request, "detail_post.html", {'forms':forms,'posts': posts,'comments':comments})
Why is the post message is not being saved. I got status code 200 in console, also i get the entered data, but the form is not being saved...Any help is much appreciated
I think the problem is that your form excludes title field, but it's required according to Comment definition. You need to give the title to comment instance then save it:
def detail(request, id):
posts = Post.objects.get(id=id)
comments = posts.comment_set.all()
forms = CommentForm
if request.method == 'POST':
form = CommentForm(request.POST,instance=posts)
print form
if form.is_valid():
# create a comment instance in memory first
comment = form.save(commit=False)
# fill out the title field
comment.title = posts
comment.save()
else:
print form.errors
else:
form = PostForm()
return render(request, "detail_post.html", {'forms':forms,'posts': posts,'comments':comments})
Also, I don't know why you use plural form for one instance, like posts should be post because you use objects.get(), make your code more readable would save some confusion for other people.

Categories