How do I resolve IntegrityError: NOT NULL constraint failed? - django

I try to let user add comments to blog post am making...
When I run makemigrations and migrate, everything seemed fine . The form displayed well but shows the following error when I fill the form and click on the submit button.
Django.db.utils.IntegrityError: NOT NULL constraint failed: blog_comment.author_id
Am new to Django and following a tutorial. The tutorial doesn't have users except the super user. I learnt about users and so I let user register to use the blog. The tutorial provided a name field in the form so commenter can enter their name. Here, I want to use the current user for this field(see my models.py below to see how I have done this).
Any help to solve this will be appreciated.
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
comment = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.author} on {self.post}'
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('comment',)
views.py
login_required
def post_detail(request, post, pk):
post = get_object_or_404(Post, id=pk, slug=post, status='published')
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
return render(request,
'post_detail.html',
{'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
PS: I have seen similar questions like this and deleted my migrations file and re-ran migrations but it didn't still work.

In the if comment.is_valid(): block,
Before;
new_comment.save()
Add,
new_comment.author = request.user

Related

How do i fix this error in my Comments view in my Django app?

I'm trying to develop an app in Django. At the moment I'm trying to create a comment section for the users to write and submit comments by using a form. I made a template which shows the info of a movie as well as a form through which users can write comments on the film.
The problem is that when I write the comment and try to submit it this error shows up :
IntegrityError at /myapp2/2/
NOT NULL constraint failed: myapp2_comentario.pelicula_id
my Views.py
def detallesPelicula(request, pelicula_id):
peliculas = get_list_or_404(Pelicula.objects.order_by('titulo'))
pelicula = get_object_or_404(Pelicula, pk=pelicula_id)
actor = get_list_or_404(Actor.objects)
comentarios = Comentario.objects.filter(pelicula=pelicula).order_by('fecha')
if request.method =='POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
comment_form.save()
texto = request.POST.get('texto')
comentario = Comentario.objects.create(
usuario=request.user, pelicula=pelicula, texto=texto)
comentario.save()
return HttpResponseRedirect(pelicula.get_absolute_url())
else:
comment_form= CommentForm()
context = {'pelicula': pelicula, 'peliculas': peliculas,
'comentarios':comentarios,'comment_form':comment_form}
return render(request, 'detallesPelicula.html', context)
my Forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comentario
fields = ['texto']
my Models.py
class Comentario(models.Model):
usuario = models.ForeignKey(Usuario, on_delete=models.CASCADE)
pelicula =models.ForeignKey(Pelicula, on_delete=models.CASCADE)
fecha = models.DateTimeField(auto_now_add=True,null=True,blank=True)
texto = models.TextField(max_length=2000, default="")
Note: the users are taken from the Django authentification system.
Help is very much appreciated.
# remove this line to fix the problem
comentario.save()
The above line of code does not have pelicula field set. Your models.py defines it as a required field, that is why you are getting IntegrityError. You can delete the code because
the preceding line of code
# this should be valid because it contains all the required fields
comentario =
Comentario.objects.create(usuario=request.user, pelicula=pelicula, texto=texto)
has already created the comment.
comment_form.save()
will try to create a new Comment, but the form doesn't have usuario or pelicula set, hence the error. It would be best to include pelicula in the form as a hidden field. But for User, you can do this:
if comment_form.is_valid():
comentario = comment_form.save(commit=False)
comentario.usuario = self.request.user
comentario.save()
If your code reached Comentario.objects.create that would create a second Comment, so if the first works that is not needed.
in line of code CommentForm(data=request.POST) you can try CommentForm(request.POST or None). Then in the line comment_form.save() replace using instance new object comentario comentario = comment_form.save(commit=False)
Please following the completed of code
def detallesPelicula(request, pelicula_id):
peliculas = get_list_or_404(Pelicula.objects.order_by('titulo'))
pelicula = get_object_or_404(Pelicula, pk=pelicula_id)
actor = get_list_or_404(Actor.objects)
comentarios = Comentario.objects.filter(pelicula=pelicula).order_by('fecha')
# initialize form to generate form template and validation form on view
# request.POST or None (request.POST for POST method and None for GET method)
comment_form = CommentForm(request.POST or None)
if request.method == 'POST':
if comment_form.is_valid():
# instance new object comentario
comentario = comment_form.save(commit=False)
# to assign usuario attribute Comentario object from current user session
comentario.usuario = request.user
# assign pelicula attribute
comentario.pelicula = comentario
# commit comentario object to database
comentario.save()
return HttpResponseRedirect(pelicula.get_absolute_url())
context = {'pelicula': pelicula, 'peliculas': peliculas,
'comentarios':comentarios,'comment_form':comment_form}
return render(request, 'detallesPelicula.html', context)

how to edit (remove) entries from a django formset

Intro: I have a post which can have multiple images I achieving this with the help of 2 models namely. Post and Prep. The post model has a user, title, a message and a post_image
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts')
title = models.CharField(max_length=250, unique=True)
message = models.TextField()
post_image = models.ImageField(upload_to='post_images/')
I am using another model to get additional images called Prep This can have multiple images.
class Prep (models.Model): #(Images)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='post_prep')
image = models.ImageField(upload_to='post_prep_images/', blank=True, null=True)
image_title = models.CharField(max_length=100)
image_description = models.CharField(max_length=250)
However unlike before each of the images from the prep model has a image_title and a image_description
The Issue: I am able to create a post successfully and also almost edit the post with one exception I cannot reduce the number of images.
If I have 3 Prep images I can add more images up to the max allowed
I can edit existing images
I cannot reduce the number of prep images
I get an error in the form
This field is required.
How do I fix this error
my post_edit view
def post_edit(request, slug):
post = get_object_or_404(Post, slug=slug)
ImageFormSet = modelformset_factory(Prep, fields=('image', 'image_title', 'image_description'), extra=7, max_num=7,
min_num=2)
if post.user != request.user:
raise Http404()
if request.method == "POST":
form = PostEditForm(request.POST or None, request.FILES or None, instance=post)
formset = ImageFormSet(request.POST or None, request.FILES or None)
if form.is_valid() and formset.is_valid():
form.save()
data = Prep.objects.filter(post=post)
for index, f in enumerate(formset):
if f.cleaned_data:
if f.cleaned_data['id'] is None:
photo = Prep(post=post, image=f.cleaned_data.get('image'), image_title=f.cleaned_data.get('image_title'),
image_description=f.cleaned_data.get('image_description'))
photo.save()
#I thought the below code will do the trick but it doesn't seem to be
elif f.cleaned_data['image'] is False or f.cleaned_data['image_title'] is False or f.cleaned_data['image_description'] is False:
photo = Prep.objects.get(id=data[index].id)
photo.image.delete()
photo.image_title.delete()
photo.image_description.delete()
photo.id.delete()
else:
photo = Prep(post=post, image=f.cleaned_data.get('image'), image_title=f.cleaned_data.get('image_title'),
image_description=f.cleaned_data.get('image_description'))
d = Prep.objects.get(id=data[index].id)
d.image=photo.image
d.image_title=photo.image_title
d.image_description=photo.image_description
d.save()
return HttpResponseRedirect(post.get_absolute_url())
else:
form = PostEditForm(instance=post)
formset = ImageFormSet(queryset=Prep.objects.filter(post=post))
context = {'form': form, 'post': post, 'formset': formset}
return render(request, 'posts/post_edit.html', context)
can_delete=True, in modelformset_factory

Pure Django Form Tying User To Submitted Form And View

I am unsure how to tie a logged in user to a submitted form using regular Django forms. I see alot of examples using ModelForms but none (that I can tell) without using the ModelForms. In my forms.py im having a hard time figuring out how to add the author field. I cannot just add author = forms.ForeignKey or something like that. Then somehow in my view i need to call the author field to be saved into the database (my below example is my best guess and probably not right with the "tenant_form.author = request.user").
I have a model that looks like this and has a user Foreignkey setup:
class AppyModel(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
date_time_form_filled = models.DateTimeField(auto_now_add=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
I have a forms.py:
class TenantForm(forms.Form):
first_name = forms.CharField(required=False, label='First Name')
last_name = forms.CharField(required=False, label='Last Name')
I have a views.py
#login_required
def tenant_create_form_view(request):
tenant_form = TenantForm()
if request.method == 'POST':
tenant_form.author = request.user
tenant_form = TenantForm(request.POST)
if tenant_form.is_valid():
print(tenant_form.cleaned_data)
AppyModel.objects.create(**tenant_form.cleaned_data)
else:
print(tenant_form.errors)
context = {
'form': tenant_form
}
return render(request, 'fill_appy.html', context)
You should add author when the form is valid,
tenant_form = TenantForm()
if request.method == 'POST':
tenant_form = TenantForm(request.POST)
if tenant_form.is_valid():
obj = tenant_form.save(commit=False)
obj.author = request.user #add author here
obj.save()
# .. rest of code

Django blog with picture

I have this in my database
paragraph1
paragraph2
paragraph2
I would like to place a picture in between paragraphs.
I tried this
<img src="where/photo/is">
class Post(models.Model):
STATUS_CHOICES = (
('draft','Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date ='publish')
author = models.ForeignKey(User, related_name='blog_posts')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
image = models.ImageField(upload_to='posts', default='path/to/my/default/image.jpg')
status = models.CharField(max_length=10, choices=STATUS_CHOICES,
default='draft')
objects = models.Manager()
published = PublishedManager()
tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[self.slug])
Note: This is the post table that takes the data in paragraphs, there is not picture in between, I would like to add it after getting this text body.
Here is my view
current_site = get_current_site(request)
namesite = current_site.name
domain = current_site.domain
post = Post.published.get(slug=post)
profile = Profile.objects.get(id=1)
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
#create Comment object but do not say to database just yet
new_comment = comment_form.save(commit=False)
#Assigng the current post to the comment
new_comment.post = post
#save the comment to the database
new_comment.save()
comment_form = CommentForm()
else:
comment_form = CommentForm()
return render(request, 'blog/detail.html',
{'post': post, 'comments': comments,
'comment_form': comment_form, 'namesite': namesite, 'domain': domain, 'profile': profile })
in the database and I use the | safe filter, but that still prints the same as above.
Do you have any idea how to perform that acction?
Hi If you want to create long description with image means you can go with django-ckeditor link, this package will provide you the RichTextField so you can create the bulk paragraphs with images.

Django editing user's posts

I am working in a blog application using django. A user can add posts and edit their own posts. However, I am having trouble with retrieving user's posts. Here is a similar question, but it does not work with my application: Django edit form based on add form? Any help is truly appreciate
Here is my code:
#login_required
def edit(request, id):
if id:
post = get_object_or_404(BlogPost, id=id)
if post.author != request.user:
return render(request, "403.html")
else:
post = BlogPost(author=request.user)
if request.method == "POST":
form = AddPost(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
messages.add_message(request, messages.SUCCESS,
'You have succesfully updated your post')
return redirect('homepage')
else:
form = AddPost(instance=post)
return render(request, 'blog/update.html', {'form': form})
Here is my model:
class BlogPost(models.Model):
title = models.CharField(
max_length=100, null=False, blank=False, unique=True)
content = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.CharField(max_length=50).......
Your author field is a CharField. I'm not sure what you're putting into that field, or how you're setting it, but it will never equal request.user, because that is an instance of your User model.
Normally the author field would be a ForeignKey to User, so that the comparison would be true for those posts authored by the current user. If you are putting the username into the author field, you could compare with that: if post.author != request.user.username - but I would really not recommend doing that, as you are breaking normalization for no good reason.
(Also note my other comment: your first else clause looks like it should be one indent to the left: ie under if id, not if post.author....)