Creating a Post but got an IntegrityError - django

I'm trying to create a post and update my list of posts. I currently get this error IntegrityError at /posts/create/ NOT NULL constraint failed: posts_post.publish Not sure what the error means and how to fix it. The files below are my posts/views.py, forms.py, post_forms.py and models
def posts_create(request):
# return HttpResponse("<h1> Create a posts. </h1>")
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
context = {
"form": form
}
# if request.method == "POST":
# print("This is the content: ", request.POST.get("content"))
return render(request, "post_form.html", context)
def posts_detail(request, id):
instance = get_object_or_404(Post, id=id)
context = {
"user": instance.user,
"instance": instance
}
return render(request, "posts_detail.html", context)
def posts_list(request):
# return HttpResponse("<h1> List a posts. </h1>")
# TODO: Privacy stuff
queryset = Post.objects.all()
context = {
"object_list": queryset,
"user": "username"
}
return render(request, "post.html", context)
Models for post:
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
status = models.CharField(max_length=6, choices=Status, default=POST)
content = models.TextField()
publish = models.DateField(auto_now=False, auto_now_add=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
privacy = models.IntegerField(choices=Privacy, default=PUBLIC)
unlisted = models.BooleanField(default=False)
This is the post_form.html
<html>
<body>
<h3>Create Post</h3>
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Share" />
</form>
</body>
</html>
This is the respective forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"content"
]

from datetime import datetime
def posts_create(request):
# return HttpResponse("<h1> Create a posts. </h1>")
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.publish = datetime.now()
instance.save()
context = {
"form": form
}
# if request.method == "POST":
# print("This is the content: ", request.POST.get("content"))
return render(request, "post_form.html", context)
do this in your view. import the first line then change your view

Related

Django refreshing records at template only after re-running server

I've just started learning Django and I making my first App. I'm having that weird problem when i adding record to database, it actually adding it there but it won't show them at my page until i reload server by following command
python manage.py runserver
views.py
from django.shortcuts import render, redirect
from .models import Students
student_data = Students.objects.all()
def homePage(request):
return render(
request,
"pages/homePage.html",
{"student_data": student_data},
)
def createStudent(request):
form = StudentForm()
if request.method == "POST":
form = StudentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect("homePage")
context = {"form": form}
return render(request, "pages/addStudent.html", context)
def updateStudent(request, pk):
student = Students.objects.get(unique_id=pk)
form = StudentForm(instance=student)
if request.method == "POST":
form = StudentForm(request.POST, request.FILES, instance=student)
if form.is_valid():
form.save()
return redirect("homePage")
context = {"form": form}
return render(request, "pages/addStudent.html", context)
def deleteStudent(request, pk):
student = Students.objects.get(unique_id=pk)
if request.method == "POST":
student.delete()
return redirect("homePage")
context = {"object": student}
return render(request, "pages/delete-template.html", context)
def viewStudent(request, pk):
student = Students.objects.get(unique_id=pk)
context = {"student": student}
return render(request, "pages/view_student.html", context)
models.py
class Students(models.Model):
name = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
card_id = models.IntegerField()
unique_id = models.UUIDField(
default=uuid.uuid4,
unique=True,
primary_key=True,
editable=False)
student_image = models.ImageField(null=True, blank=True, default="default_student.jpg")
class Meta:
verbose_name_plural = 'Students'
#Methods
def __str__(self):
return f'{self.name} {self.surname}'
addStudent.html
{% extends "main.html" %}
{% block addStudent %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit"/>
</form>
{% endblock addStudent %}
Here's the image of my home page:
Home Page
And this is a form to create a record in database:
addStudent.html page
But after submiting form, django not showing me a record, i've just created.
It just displays nothing.
I need to restart server to see record:
after re-running server
I think that bug appeared after I've started working with static files and added
student_image = models.ImageField(null=True, blank=True, default="default_student.jpg")
Has anyone faced that problem before?
You need to execute the student_data query on every request, currently it's only being executed once and the results of that first query are being reused. You can do this in two ways:
First, you can call .all() on the queryset to execute it again if you want to keep student_data as a global variable
from django.shortcuts import render
from .models import Students
student_data = Students.objects.all()
def homePage(request):
return render(
request,
"pages/homePage.html",
{"student_data": student_data.all()},
)
Second, you can define the queryset on every call to the view to get fresh data
from django.shortcuts import render
from .models import Students
def homePage(request):
return render(
request,
"pages/homePage.html",
{"student_data": Students.objects.all()},
)

Why is this ModelForm not valid

I'm new to coding with django, and I'm trying to add comments to my blog app, but I'm having trouble with the validation of this form, it always returns False with form.is_valid(), so the object is never saved
views.py
def blog_post_detail_view(request, slug):
obj = get_object_or_404(BlogPost, slug=slug)
comments = Comment.objects.filter(blog_post=obj)
initial_data = {
"blog_post": obj,
}
form = CommentModelForm(request.POST or None, initial=initial_data)
if form.is_valid():
comment_obj = form.save(commit=False)
comment_obj.user = request.user
comment_obj.save()
form = CommentModelForm()
else:
print('not clean')
context = {
"object": obj,
"comments": comments,
"form": form,
}
template_name = 'blog/detail.html'
return render(request, template_name, context)
forms.py
from django import forms
from .models import Comment
class CommentModelForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['content','blog_post']
HTML
<form method='POST' action='.'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Send</button>
</form>
models.py
class Comment(models.Model):
content = models.TextField(max_length=300)
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, default=1)
blog_post = models.ForeignKey(BlogPost, null=True, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return str(self.user.username)
def __str__(self):
return str(self.user.username)

IntegrityError, NOT NULL constraint failed

I want to add tags to posts in my Django app.
I can add tags through the admin interface, but when I try to do it through the form I created, I get an IntegrityError.
I couldn't find the solution in the existing topics with the same error. I ran makemigrations and migrate.
From models.py:
class Post(models.Model):
title = models.CharField(null=False, blank=False)
text = models.TextField()
class Tag(models.Model):
post = models.ForeignKey('my_app.Post', on_delete=models.CASCADE, related_name='tags')
tag_text = models.CharField()
The view:
def post_add_tags(request, pk):
post= get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = TagForm(request.POST)
if form.is_valid():
tag = form.save()
tag.post= post
tag.save()
return redirect("single_post_view", pk=post.pk)
else:
form = TagForm()
return render(request, "add_tags.html", {"form": form})
The form from forms.py:
class TagForm(forms.ModelForm):
class Meta:
model = Tag
fields = ["tag_text"]
The template:
<form method="POST"> {% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Add tags</button>
</form>
The error:
IntegrityError at /post/4/add_tags/
NOT NULL constraint failed: my_app_tag.post_id
I'm using Django version 2.2, Python 3.6.8.
do not save form until you set all required fields, specially foreign keys :
def post_add_tags(request, pk):
post= get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = TagForm(request.POST)
if form.is_valid():
tag = form.save(commit=False)
tag.post= post
tag.save()
return redirect("single_post_view", pk=post.pk)
else:
form = TagForm()
return render(request, "add_tags.html", {"form": form})

How to save the information of a form so that it appears in the Admin Site Panel?

I am making a web page and there is a contact section in which I am looking for people to leave a message and then I contact them, I want the information entered in the form to be stored in the database so that later I can see it in the Django Admin Page.
# models.py
from django.db import models
class Contact(models.Model):
name = models.CharField(max_length = 100, verbose_name = "Nombre")
email = models.CharField(max_length = 100, verbose_name = "Email")
issue = models.CharField(max_length = 200, verbose_name = "Asunto")
text = models.TextField(verbose_name = "Mensaje")
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length = 100, label = "Nombre")
email = forms.EmailField(label = "Correo electrónico")
issue = forms.CharField(max_length = 200, label = "Asunto")
text = forms.CharField(label = "Mensaje")
# views.py
from django.views.generic import TemplateView
from contact.forms import ContactForm
from django.shortcuts import render
class Contact(TemplateView):
template_name = 'contact/contact.html'
def get(self, request):
form = ContactForm
return render(request, self.template_name, {'form': form})
def post(self, request):
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
issue = form.cleaned_data['issue']
text = form.cleaned_data['text']
form = ContactForm()
args = {
'form': form,
'name': name,
'email': email,
'issue': issue,
'text': text,
}
return render(request, self.template_name, args)
<!-- And this is the form -->
<div class="page-section contact-page">
<div class="contact-warp">
<div class="row">
<div class="col-xl-6 p-0">
<div class="contact-text">
<span>¡Hola!</span>
<h2>Contáctame</h2>
<form class="contact-form" method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="site-btn">Enviar mensaje</button>
</form>
</div>
</div>
</div>
</div>
</div>
I have made several attempts but I can not get the information to appear in the admin, (I have already registered the model in the admin).
Please, help me :(
Well, as you are not using ModelForm, then you need to save those values manually in the View. Like this:
def post(self, request):
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
issue = form.cleaned_data['issue']
text = form.cleaned_data['text']
args = {
'form': form,
'name': name,
'email': email,
'issue': issue,
'text': text,
}
Contact.objects.create(**args) # <-- saving to DB
# rest of the code
I am not sure why you are using TemplateView, because FormView is much more appropriate for handling form. For example:
class ContactView(FormView):
form_class = ContactForm
template_name = 'contact/contact.html'
success_url= '/'
def form_valid(self, form):
name = form.cleaned_data['name']
email = form.cleaned_data['email']
issue = form.cleaned_data['issue']
text = form.cleaned_data['text']
args = {
'form': form,
'name': name,
'email': email,
'issue': issue,
'text': text,
}
Contact.objects.create(**args)
return super(ContactView).form_valid(form)
Also, if you use ModelForm, then you can simply store data like this:
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = "__all__"
# usage
if form.is_valid():
form.save()
# rest of the code
You need to call form.save() so your data gets saved. It's not being saved currently. Call it inside form.is_valid(): block.
Also, you don't need to pass the form values. You can access them using form.data.field_name.

MultipleChoiceField form not displaying user's instance of form

I've implemented a MultipleChoiceField form with a CheckboxSelectMultiple. It works perfectly in that the form is displayed and user selected options are saved to the BaseServicesOffered model as desired. The problem is that when the user goes back to the form, the checkboxes that the user had previously selected/submitted are not selected -- they are all unchecked. I'd imagine that it's a problem with my views.py. Here is my code:
models.py
class BaseServicesOffered(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
service = models.CharField(max_length=255, default='', null=True, blank=True)
def __str__(self):
return self.user.username
forms.py
class BaseServicesOfferedForm(forms.ModelForm):
service = forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user') #this takes in the value of 'user', which is passed from the view function.
super(BaseServicesOfferedForm, self).__init__(*args, **kwargs)
self.fields['service'].choices = [(t.id, t.service) for t in AllServices.objects.filter(industrycode=user.userprofile.industry)]
class Meta:
exclude = ('user',)
model = BaseServicesOffered
views.py
#login_required(login_url="/accounts/login/")
def baseservicesoffered(request):
try:
base_services_offered = BaseServicesOffered.objects.create(user=request.user)
except:
pass
user = request.user
instance = get_object_or_404(BaseServicesOffered, user=user)
form = BaseServicesOfferedForm(request.POST or None, user=request.user, instance=instance)
if request.method == 'POST':
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
service = form.cleaned_data['service']
services = [int(i) for i in service]
instance.service = services
instance.save()
return redirect('/accounts/profile/')
else:
context = {'form': form}
return render(request, 'accounts/setup8.html', context)
context = {'form': form}
return render(request, 'accounts/setup8.html', context)
setup8.html
<form id="post_form" method="post" action="" enctype="multipart/form-data">
{{ form.non_field_errors }}
{% csrf_token %}
{{ form.as_p }}
<div class="submitbutton">
<button type="submit">
SUBMIT
</button>
</div>
</form>
Update:
This is how you store a list of ints in the Charfield:
service = form.cleaned_data['service']
services = [int(i) for i in service] #converts list of strings to list of ints
instance.service = services
I've updated my code above with this.
multiple_choice = forms.MultipleChoiceField(
label=u"Select multiple",
choices=MY_CHOICES,
widget=forms.widgets.CheckboxSelectMultiple,
initial=(c[0] for c in MY_CHOICES)
)
You should set the inital parameter for the options to be checked for a particular user.