I have created a blog website and I want to display images for every post like YouTube thumbnails. I created an image field in my Post Class but it is not saving my image in the media folder when I create a post.
Post class in models.py:
class Post(models.Model):
name = models.CharField(default='Concert', max_length=100)
invite = models.ImageField(default='invite.jpg', upload_to='invite_pics')
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
This is my CreatePost class in views.py:
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
template_name = 'home_page/post_form.html'
fields = ['name', 'invite']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
I have set the MEDIA_ROOT and MEDIA_URL in settings.py:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
post_form.html:
<div class="container">
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Create New Event</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
</div>
So as I have said earlier, the image is not getting saved to media/invite_pics what should I do?
In order to submit data and files, you need to specify the enctype="…" parameter of the form:
<form enctype="multipart/form-data" method="POST">
…
</form>
Related
I have encountered a funny challenge, as am building some apps where they want track some expenses and revenues profits ...
I used generic views to create and get details and delete, all work fine with expenses, but I copied the same code and I used it for revenues from expenses you can't imagine this view is rendering a button only yet it has a form, NOTE SAME CODE WORK WELL ON EXPENSES. I even exchanged templates but it kept rendering the former content even after changing the template. it doesn't matter what's in the template the view just renders the same thing even when I remove the form, even when I put pass.
class AccountsRevenueCreate(CreateView):
template_name='dashboard/expense_create.html'
model= AccountsExpense
success_url = reverse_lazy('dashboard:expenses')
form_class=AccountsExpenseForm
and the form
class AccountsRevenueForm(forms.ModelForm):
class Meta:
model = AccountsRevenue
fields = '__all__'
and in the template
<div class="row">
<div class="col-12">
<h5 class="form-title"><span>revenue Update
</span></h5>
</div>
<form method="post", action="{% url
'dashboard:revenue_add' %}">
{% csrf_token %}
{% comment %} {{ form|crispy }} {% endcomment %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary col-12 col-sm-12">Save
</button>
</form>
</div>
and the URLs
path ('accounts/revenues/create/', AccountsRevenueCreate.as_view(), name='revenue_create'),
I have chosen to show you only where the problem is not paste unnecessary code
here are the models you requested me to update
from django.db import models
class AccountsRevenue(models.Model):
revenue_of = models.CharField(max_length=250, default='',null=False)
revenue_by = models.CharField(max_length=250, default='',null=False)
amount = models.IntegerField( default='100,000')
day_on_which = models.DateField(null=True, blank=True)
evidence_document = models.ImageField(upload_to = 'uploads/', blank=True, default='')
signature = models.ImageField(upload_to = 'uploads/', blank=True, default='')
def __str__(self):
return str(self.revenue_of)
def get_absolute_url(self):
return reverse('dashboard:revenue', kwargs= {'pk':self.pk} )
def get_document(self):
if self.evidence_document and hasattr(self.evidence_document, 'url'):
return self.evidence_document.url
else:
return "/static/assets/img/user.png"
class AccountsExpense(models.Model):
expense_of= models.CharField(max_length=250, default='',null=False)
expense_by = models.CharField(max_length=250, default='',null=False)
amount = models.IntegerField( default='100,000')
day_on_which = models.DateField(null=True, blank=True)
evidence_document = models.ImageField(upload_to = 'uploads/',
blank=True, default='')
signature = models.ImageField(upload_to = 'uploads/', blank=True,
default='')
def __str__(self):
return str(self.expense_of)
def get_absolute_url(self):
return reverse('dashboard:expense', kwargs= {'pk':self.pk} )
def get_document(self):
if self.evidence_document and hasattr(self.evidence_document,
'url'):
return self.evidence_document.url
else:
return "/static/assets/img/user.png"
from django.urls import URLPattern, path
from django.conf.urls.static import static
from. views import profiles, Profile_detail, Profile_update,
Profile_delete, dashboard, Profile_create,\
AccountsRevenues, revenue_detail_view, AccountsRevenueUpdate,
AccountsRevenue_delete, \
AccountsExpenses, AccountsExpenseDetail, AccountsExpenseCreate,
AccountsExpenseUpdate, AccountsExpenseDelete,\
userprofileupdate, revenue_add, AccountsRevenueCreate
app_name = "dashboard"
urlpatterns = [
path ('accounts/revenues', AccountsRevenues.as_view(), name='revenues'),
path ('accounts/revenues/<str:pk>/', revenue_detail_view,
name='revenue'),
path ('accounts/revenues/<str:pk>/update/',
AccountsRevenueUpdate.as_view(), name='revenue_update'),
path ('accounts/revenues/<str:pk>/delete/',
AccountsRevenue_delete.as_view(), name='revenue_delete'),
path ('accounts/revenues/create/', AccountsRevenueCreate.as_view(),
name='revenue_create'),
# accounts expenses
path ('accounts/expenses', AccountsExpenses.as_view(), name='expenses'),
path ('accounts/expenses/<str:pk>', AccountsExpenseDetail.as_view(),
name='expense'),
path ('accounts/expenses/<str:pk>/update/',
AccountsExpenseUpdate.as_view(), name='expense_update'),
path ('accounts/expenses/<str:pk>/delete/',
AccountsExpenseDelete.as_view(), name='expense_delete'),
path ('accounts/expenses/create/', AccountsExpenseCreate.as_view(),
name='expense_create'),
]
I have added a screenshot of what it comes out as enter image description here
left model.py, forms.py, urls.py as it was.
views.py
in the line: template_name = 'bboard/expense_create.html' replace bboard with the name of the folder where the templates are located. I have it templates/bboard. Also in your field: form_class=AccountsExpenseForm changed to form_class = AccountsRevenueForm.
And the return goes to the same page with the form: success_url = reverse_lazy('revenue_create').
success_url can then be returned to what it was, now you need to make sure that everything works.
views.py
class AccountsRevenueCreate(CreateView):
template_name = 'bboard/expense_create.html'
model = AccountsExpense
success_url = reverse_lazy('revenue_create')
form_class = AccountsRevenueForm
expense_create.html
in the template you have an error form method="post", there should not be a comma.
<div class="row">
<div class="col-12">
<h5 class="form-title"><span>revenue Update
</span></h5>
</div>
<form method="post" action="{% url 'revenue_create' %}">
{% csrf_token %}
{% comment %} {{ form|crispy }} {% endcomment %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary col-12 col-sm-12">Save
</button>
</form>
</div>
Followed the link: http://localhost:8000/accounts/revenues/create/
Screenshot attached:
views.py
class PostCreatView(LoginRequiredMixin, CreateView):
model = Posts
fields = ['image', 'caption']
template_name = 'home/creat-post.html'
success_url = '/home/'
def form_valid(self,form):
form.instance.user = self.request.user
return super().form_valid(form)
models.py
class Posts(models.Model):
caption = models.CharField(max_length=2200)
date_posted = models.DateTimeField(default=timezone.now())
image = models.ImageField( upload_to='PostsImages')
user = ForeignKey(User, on_delete=models.CASCADE ,related_name='UserPosts')
def __str__(self):
return f"Post {self.id} ({self.user.username})'s"
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
#img = make_square(img, 1080, 1080)
img.save(self.image.path)
class Meta:
ordering = ['-date_posted']
creat-post.html
{% extends "home/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div>
<form method="POST">
<fieldset>
<legend >Creat Post</legend>
{% csrf_token %}
{{ form|crispy }}
</fieldset>
<button class="btn btn-primary" type="submit">Post</button>
</form>
</div>
{% endblock %}
So I created a creatview to add create new post. However when I go to the link and add photo then hit submit, it gives me as I haven't uploaded an image.
However, I am able to add images to a new Post from the admin normally.
Try to add enctype in your template:
<form method="post" enctype="multipart/form-data">
Hi i'm trying to add some funcionality to my blog post app, i'd like to paste image into post content so i figured is this waw that ive created new model just for images and set it as OneToOne with my Post model
i wonder if ther is any way to set this image to content field in the post model
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class PostImage(models.Model):
post = models.OneToOneField(Post, on_delete=models.CASCADE)
image = models.ImageField(default=None, upload_to='post_pics', blank=True)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 500 or img.width > 500:
output_size = (500, 500)
img.thumbnail(output_size)
img.save(self.image.path)
vievs.py
def home(request):
context = {
'posts': Post.objects.all(),
'user_posts': "active",
}
return render(request, 'blog/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 5
post_template.html
{% extends "blog/base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Blog Post</legend>
{{form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Well i've found another solution i've used CKEditor and now everything works fine
pip install pillow
& in static/post_pics (see the img.jpg ...png ) it's save ?
I am following buckys django tutorial, he explained how to add albums but not song, i want to try adding songs to specific album but it is not working.
I have added a SongCreate view to my views.py, i also created a song_form.html template for inputting song details.I have also tried the form_valid method, but it doesnt just work.
My views.py
class AlbumCreate(CreateView):
model=Albums
fields=['alb_title','alb_genre','alb_logo','alb_artist']
class SongCreate(CreateView):
model = Song
fields = ['song_title', 'song_format']
def form_valid(self, form):
album = get_object_or_404(Albums, pk=self.kwargs['pk'])
form.instance.album = album
return super(SongCreate, self).form_valid(form)
#My urls.py
app_name ='music'
urlpatterns = [
path('',views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('album/add/', views.AlbumCreate.as_view(), name='album-add'),
path('album/<int:pk>/songadd/', views.SongCreate.as_view(),
name='song-add'),
path('album/<int:pk>/', views.AlbumUpdate.as_view(), name='album-
update'),
path('album/<int:pk>/delete/', views.AlbumDelete.as_view(),
name='album-delete'),
]
#My song_form.html template
{% extends 'music/base.html' %}
{% block title %}Add New Song{% endblock %}
{% block body %}
<div class="container-fluid">
<h4>Add the details of the Song in the given fields.</h4>
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
<form class='form-horizontal' action=""
method="post"
enctype="multipart/form-data">
{% csrf_token %}
{% include 'music/form-template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-
success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
#Models.py
class Albums(models.Model):
alb_title = models.CharField(max_length = 250)
alb_genre = models.CharField(max_length = 250)
alb_logo = models.FileField()
alb_artist = models.CharField(max_length = 250)
def get_absolute_url(self):
return reverse("music:detail", kwargs={"pk": self.pk})
def __str__(self):
return self.alb_title + '-' + self.alb_artist
class Song(models.Model):
song = models.ForeignKey(Albums, on_delete = models.CASCADE)
song_title = models.CharField(max_length = 250)
song_format = models.CharField(max_length = 10)
is_favourite = models.BooleanField(default=False)
def __str__(self):
return self.song_title
def get_absolute_url(self):
return reverse('music:detail', kwargs={'pk': self.song.pk})
When add song is clicked it directs me to a form to fill song detail, but when i tried it i got:
IntegrityError at /music/album/song/add/
NOT NULL constraint failed: music_song.song_id
you must :
def create_song(request):
if request.method == "POST":
form.save()
I give you the way I use form_valid()
def form_valid(self, form):
album = get_object_or_404(Albums, pk=self.kwargs['pk'])
form = form.save(commit=False)
form.album = album
form.save()
return super().form_valid(form)
If it doesn't work, it means you have changes not reflected in your database. Run ./manage.py makemigrations and ./manage.py migrate. It might be necessary, if possible, to drop and recreate the whole db.
I am using Django CreateView on model object. The form gets rendered but on submitting Post button, nothing happens. In console I am receiving code 200 (Success) but object is not created. Also, I am using same HTML template and same code for Update View and it is working perfectly. Please help.
class EventCreateView(LoginRequiredMixin, CreateView):
model = Event
fields = ['name', 'event_attendees']
def form_valid(self, form):
form.instance.creator = self.request.user
return super().form_valid(form)
Model
name = models.CharField(max_length=100)
date = models.DateTimeField(default=timezone.now)
location = models.CharField(max_length=16, choices=EVENT_VENUES, default='sec-1, noida')
event_attendees = models.FileField(upload_to='documents/', default='')
creator = models.ForeignKey(User, on_delete=models.CASCADE)
form_rollout_time = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('event-detail', kwargs={'pk': self.pk})
Html template
{% extends "events/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New Event</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
Urls
urlpatterns = [
path('', EventListView.as_view(), name='event-home'),
path('user/<str:username>', UserEventListView.as_view(), name='user-events'),
path('event/<int:pk>/', EventDetailView.as_view(), name='event-detail'),
path('event/new/', EventCreateView.as_view(), name='event-create'),
path('event/<int:pk>/update/', EventUpdateView.as_view(), name='event-update'),
path('event/<int:pk>/delete/', EventDeleteView.as_view(), name='event-delete')
]
update code like this
def form_valid(self, form):
obj = form.save(commit=False)
obj.creator = self.request.user
obj.save()
try this
Solved the issue by overriding method form_invalid(). Apparently, the issue was in the implementation with FileField but was suppressed with the default implementation of form_invalid. On overriding the method, the actual issue arose.