Adding image for blog posts - django

Coding some kind of blog with django, and I can't make homepage to contain images of the articles... It just doesn't upload a image...
my Views.py :
class AddPostView(CreateView):
model = Post
form_class = PostForm
template_name = 'add_post.html'
my Models.py:
class Post(models.Model):
title = models.CharField(max_length=255)
title_tag = models.CharField(max_length=255, default="YNTN")
#author = models.ForeignKey(User, on_delete=models.CASCADE)
body = RichTextField(blank=True, null=True)
image = models.ImageField(upload_to="profile_pics", blank=True, null=True)
#body = models.TextField()
post_date = models.DateField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name="blog_posts")
def total_likes(self):
return self.likes.count()
def __str__(self):
return (self.title + " | " + str(self.author))
def get_absolute_url(self):
return reverse("home")
My Forms.py:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'title_tag', 'body', 'image')
widgets = {
'title': forms.TextInput(attrs={'class':'form-control', 'placeholder':'Title of the Blog'}),
'title_tag': forms.TextInput(attrs={'class':'form-control', 'placeholder':'Copy the title with no space and a hyphen in between'}),
'body': forms.Textarea(attrs={'class':'form-control', 'placeholder':'Content of the Blog'}),
}
and my add_post.html :
{% extends 'base.html' %}
{% block title %}Make an article{% endblock %}
{% block content %}
{% if user.is_authenticated %}
<h1>Make an article</h1>
<div class="form-group">
<form method="POST">
<br/>
{% csrf_token %}
{{ form.media }}
{{ form.as_p }}
<button class="btn btn-dark">POST</button>
</div>
{% else %}
<h1>You are not allowed to post! You need to Log in or Register</h1>
{% endif %}
{% endblock %}
I tried on many ways but never worked..

You are missing enctype="multipart/form-data" (as mentioned in the documentation) in the form tag inside the html template. Update the html file like this:
<form method="POST" enctype="multipart/form-data">
<br/>
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-dark">POST</button>
</form>

Related

Django Change boolean field with click

I am working on a To-do app. The individual to-dos reference a to-do list via a foreign key and the to-do lists reference a project via a foreign key.
I want the to-do's status to be set to true when clicked. I have seen some tutorials where this is done but I haven't been able to get this to work yet.
Here are the models:
class Project(models.Model):
title = models.CharField(max_length= 200)
description = tinymce_models.HTMLField()
status = models.CharField(max_length=20, choices=PROJECT_CHOICES, default="active")
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse ('project_detail', args=[str(self.id)])
class ProjectTodoGroup(models.Model):
title = models.CharField(max_length=250)
description = tinymce_models.HTMLField()
project = models.ForeignKey(Project, blank=True, on_delete=models.CASCADE, related_name='todo_group')
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.title
class ProjectTodo(models.Model):
title = models.CharField(max_length= 250)
notes = tinymce_models.HTMLField()
status = models.BooleanField(default=False)
projectgroup = models.ForeignKey(ProjectTodoGroup, blank=True, null=True, on_delete=models.CASCADE, related_name='todo_set')
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.title
The view:
model = ProjectTodo
fields = ['status']
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
context['project'] = get_object_or_404(Project, id=self.kwargs.get('pk'))
return context
def get_success_url(self):
return reverse('company_project:todo_group_detail', args=[self.kwargs.get('pk'), (self.object.id)])
Everything I have tried to far with the view hasn't worked.
The template:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="section-container container">
<div class="todo-group">
<h2>{{ projecttodogroup.title }}</h2>
<p>{{ projecttodogroup.description | safe }}</p>
</div>
<div><b>Todos</b></div>
{% if projecttodogroup.todo_set.all %}
{% for todo in projecttodogroup.todo_set.all %}
<div class="todos" style="padding: 10px;">
{{ todo.title }}
</div>
{% endfor %}
{% else %}
<p>No Todos have been have been added yet.</p>
{% endif %}
<h1>Add Todo</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.media }}
{{ form|crispy }}
<input type="submit" value="save">
</form>
</div>
{% endblock content %}

Django UNIQUE constraint failed: players_comment.user_id

I'm trying to post comment but it's not getting posted, rather this error is appearing UNIQUE constraint failed: players_comment.user_id. I don't know why this error is occuring.
My forms.py:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body', 'transfernews')
My models.py :
class Transfernews(models.Model):
player_name = models.CharField(max_length=255)
player_image = models.CharField(max_length=2083)
player_description = models.CharField(max_length=3000)
date_posted = models.DateTimeField(default=timezone.now)
class Comment(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
transfernews = models.ForeignKey(Transfernews, related_name="comments", on_delete=models.CASCADE)
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.transfernews.player_name, self.user.username)
My views.py:
def transfer_targets(request):
transfernews = Transfernews.objects.all()
form = CommentForm(request.POST or None)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.user = request.user
new_comment.save()
return redirect('transfernews/')
return render(request, 'transfernews.html', {'transfernews': transfernews, 'form': form})
My transfernews.html:
{% for transfer in transfernews %}
{% if not transfer.comments.all %}
No comments Yet...
{% else %}
{% for comment in transfer.comments.all %}
<strong>
{{ comment.user.username }} - {{ comment.date_added }}
</strong>
<br/>
{{ comment.body }}
<br/><br/>
{% endfor %}
{% endif %}
<hr>
<div>Comment and let us know your thoughts</div>
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary btn-sm shadow-none" type="submit">Post comment</button>
<button class="btn btn-outline-primary btn-sm ml-1 shadow-none" type="button">Cancel</button>
</form>
{% endfor %}
In models.py, in the comment class, change
user = models.OneToOneField(User, on_delete=models.CASCADE)
to
user = models.ForeignKey(to=User, on_delete=models.CASCADE)
One to one works both ways, user's allowed to only have one comment and a comment can belong to only one user. By changing to one to many via foreignkey you'll preserve the latter and get rid of the former constraint.

My form keep saying "This(image) field is required!" Django 3.0

I made a project with net-ninja on youtube now I am adding "uploading media" feature in my own project but it is not working although every thing is set just tell me where i m going wrong.
My form is keep asking me to upload image file even though i had already done, every time i send a post request it renders the page again with no value in image field. what is wrong here, why it is not taking image input?Don't comment set the required to false that is not the solution i don't know why some people said this to others on stackoverflow when they asked the same question as me.
My model class looks like this
class Products(models.Model):
name = models.CharField(max_length=500, unique=True, )
price = models.IntegerField()
stock = models.IntegerField()
date_added = models.DateTimeField(verbose_name="date added", auto_now_add=True, )
thumb = models.ImageField(default='default.png', blank=True)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE, default=None,)
def __str__(self):
return self.name
class Meta():
verbose_name_plural = "Products"
My form looks like this
class AddProduct(forms.ModelForm):
name = forms.CharField(widget=forms.TextInput(attrs={'placeholder':'Product Name', 'required':'True', 'class': 'form-control'}))
price = forms.IntegerField(widget=forms.NumberInput(attrs={'placeholder':'Set Price', 'required':'True', 'class': 'form-control'}))
stock = forms.IntegerField(widget=forms.NumberInput(attrs={'placeholder':'Number of items', 'required':'True', 'class': 'form-control'}))
thumb = forms.ImageField(required=False, widget=forms.ClearableFileInput(attrs={'placeholder':'Upload Picture', 'enctype' : 'multipart/form-data'}))
class Meta():
model = Products
fields = ('name', 'price', 'stock','thumb', )
HTML looks like this
<form class="row contact_form" action="/shop/add_products" method="post">
{% csrf_token %}
{% for field in form %}
<div class="col-md-12 form-group p_star">
{{ field }}
{{ field.errors }}
</div>
{% endfor %}
<!-- {% for field in form %}
{% for error in field.errors %}
<div class="col-md-12 form-group p_star">
{{ error }}
</div>
{% endfor %}
{% endfor %} -->
{% if form.non_field_errors %}
<div class="col-md-12 form-group p_star">
{{ form.non_field_errors }}
</div>
{% endif %}
<div class="col-md-12 form-group">
<button type="submit" value="submit" class="btn_3">
Add Product
</button>
</div>
</form>
My views file looks like this
#login_required(login_url='/shop/login')
def shop_add_products(request):
if request.method == 'POST':
form = AddProduct(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.profile = request.user
instance.save()
return redirect("/shop/products")
else:
form = AddProduct()
return render(request, "pillow_site_html/add_product.html", { 'form':form })
Oh sorry i didn't understood the question here, you are getting that because in fact you are not sending the picture inside your form as you have to add this to your form so it can accept files handling
<form class="row contact_form" action="/shop/add_products" method="post" enctype="multipart/form-data">

how to upload the image file and display it

I want to know how to upload and display the image.
I do have the classes in views.py.
class ArticleUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Article
fields = ('title', 'body', 'image', 'source_url')
template_name = 'article_edit.html'
def test_func(self):
obj = self.get_object()
return obj.author == self.request.user
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
template_name = 'article_new.html'
fields = ('title', 'body', 'image', 'source_url')
login_url = 'login'
def test_func(self):
obj = self.get_object()
return obj.author == self.request.user
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
And the relevant classes in the models.py are like as follow.
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(
upload_to='media/', null=True, blank=True)
source_url = models.URLField(blank=True, null=True, max_length=300)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
class Comment(models.Model):
article = models.ForeignKey(Article,
on_delete=models.CASCADE, related_name='comments', )
comment = models.CharField(max_length=140)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE),
def __str__(self):
return self.comment
def get_absolute_url(self):
return reverse('article_list')
The article_list.html file is:
{% extends 'base.html' %}
{% load static %}
{% block title %}Articles{% endblock title %}
{% block content %}
{% for article in object_list %}
<div class="card">
<div class="card-header">
<span class="font-weight-bold">{{ article.title }}</span> ·
<span class="text-muted">by {{ article.author }} |
{{ article.date }}</span>
</div>
<div class="card-body">
{{ article.body|linebreaks}}
{% comment %} {% if article.image.url|length > 0 %}
<img src="{{ article.image.url }}" width="200px">
{% else %}
<img src="{% static '/media/mrDoctor.jpg' %}" width="200px" />
{% endif %} {% endcomment %}
<img src="{% static 'articles/mrDoctor.jpg' %}" alt="Image" width="200px" />
Link
Edit
Delete
</div>
<div class="card-footer">
{% for comment in article.comments.all %}
<p>
<span class="font-weight-bold">
{{ comment.author }} ·
</span>
{{ comment }}
</p>
{% endfor %}
</div>
</div>
<br />
{% endfor %}
{% endblock content %}
The user can select the image file from the form.
I can not display the image selected from the input form shown above on the screen shot. I want to display the images dynamically, i.e., when the user choose the image file from the input form. I know I should change the part:{% static '/media/mrDoctor.jpg' %}. When I tried the commented part of article_list.html, i.e., {% if article.image.url|length > 0 %}, it did not work. I will appreciate it if you help me to fix the problem. Many thanks.
After reflecting #Hybrid suggestions, I was able to show the image on the first article but the second and the third one show only the file names.
You can do this by using JavaScript to detect when a user selects an image, and then replacing an <img /> tags src dynamically.
Example code:
<img id="image" />
<input id="files" type="file" />
<script>
document.getElementById("files").onchange = function () {
var reader = new FileReader();
reader.onload = function (e) {
// get loaded data and render thumbnail.
document.getElementById("image").src = e.target.result;
};
// read the image file as a data URL.
reader.readAsDataURL(this.files[0]);
};
</script>

Django blog post doesn't update it just creates another object

This view is supposed to find a blog post and change it's information, but instead of that it just makes a new Blog object with the new (and old) information.
The update view
#login_required
def view_updatepost(request, blog_id):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
#post = Blog.objects.get(pk=blog_id)
post_to_be_changed = get_object_or_404(Blog, pk=blog_id)
form = BlogForm(request.POST or None, instance=post_to_be_changed)
if form.is_valid():
post_to_be_changed = form.save(commit=False)
#
#
post_to_be_changed.save()
#messages.success(request, "<a href='#'>Item</a> Saved", extra_tags='html_safe')
return HttpResponseRedirect(post_to_be_changed.get_absolute_url())
context = {
'post_to_be_changed': post_to_be_changed,
'form': form,
}
return render(request, 'blog/makepost.html', context)
The template used by the view makepost.html
{% extends "base.html" %}
{% load staticfiles %}
{% block main_content %}
<!-- Page Header -->
<!-- Set your background image for this header on the line below. -->
<header class="intro-header" style="background-image: url('{% static "img/about-bg.jpg" %}')">
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="page-heading">
<h1>Make a Post</h1>
<hr class="small">
<span class="subheading">Share with the World.</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
{% if not user.is_authenticated %}
You must be <u>logged in</u> to make a post.
{% else %}
<form action="{% url "makepost" %}" method="post">
{% csrf_token %}
{{form.as_p}}
<div align="center">
<input class="btn btn-default" type="submit" value="Post to Blog" onclick="window.location='{% url "" %}';"/>
{# Home #}
</div>
</form>
{% endif %}
</div>
</div>
</div>
<hr>
{% endblock main_content %}
The models.py
from django.db import models
import datetime
# Create your models here.
class Blog(models.Model):
title = models.CharField(max_length=250)
subtitle = models.CharField(max_length=250, null = True, blank=True)
date_added = models.DateTimeField(default=datetime.datetime.now())
image = models.TextField(max_length=1000, null = True, blank=True)
tags = models.TextField(max_length=500, null=True, blank=True)
article = models.TextField(max_length=15000, null=True, blank=True)
author = models.CharField(max_length=150, null=True, blank=True)
def get_absolute_url(self):
return "/blog/%i" % self.pk
The forms.py
from django import forms
from .models import Blog
import datetime
class PostForm(forms.Form):
title = forms.CharField()
subtitle = forms.CharField(required=False)
date_added = forms.DateTimeField()
image = forms.URLField(required=False)
tags = forms.CharField(required=False)
article = forms.CharField()
author = forms.CharField()
class BlogForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'subtitle',
'image', 'tags', 'article')
It seems that you are not referring to your update view in your form action url:
<form action="{% url **"makepost"** %}" method="post">