Image upload in CreateView - python

I have a CreateView in my project to post a tweet-like-post. It has a title and content.
It look like this in views.py
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form): # Author for post (required- if no- error)
form.instance.author = self.request.user
return super().form_valid(form)
And I would like to add picture-upload column to make a persons able to upload a picture with the post.
My models.py looks like this
class Post(models.Model):
title = models.CharField(max_length=100, verbose_name='タイトル')
content = models.TextField(verbose_name='内容')
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})
I already have a uploaded_pic folder in my static with 777 permision.
Could you please tell me how to add there working picture-upload column

picture_upload = models.ImageField()
If left as is it will upload to MEDIA_ROOT, which is recommended, but if you really want to modify that directory, you can use the upload_to property.
from django.conf import settings
picture_uploaded = models.ImageField(upload_to=settings.STATIC_URL + '/uploaded_pic')

Related

how to collect the pk of the model that you are currently viewing (django)

hey I'm trying to make a question and answer project for django, how do I get the pk of the question that I am viewing right now to send an answer? I already set it up so that the url of the answer has /answer/pk of the question but I dont know how to get that info so the code knows where to post the model, how do I do that? also here is my code, thanks!
views.py
class AnswerForm(SuccessMessageMixin, CreateView):
template_name = 'forum/answer-question.html'
model = Answer
form_class = AnswerForm
success_message = 'Success!'
def form_valid(self, form, pk=None):
form.instance.question_id = Question.objects.only('id')
form.instance.user = self.request.user
form.save()
return super().form_valid(form)
forms.py
class AnswerForm(ModelForm):
class Meta:
model = Answer
fields = ['detail']
exclude = ('user', 'add_time')
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('questions/', views.QuestionsView.as_view(), name='questions'),
path('ask/', views.AskForm.as_view(), name='ask'),
path('answer/', views.AnswerForm.as_view(), name='answer'),
path('answer/<pk>', views.AnswerForm.as_view(), name='answer_with_pk'),
path('question/<pk>', views.QuestionDetailView.as_view(), name='detail'),
path('save-text', views.WriteCommentAnswerView.as_view(), name='save-text'),
path('save-vote', views.SaveVoteView.as_view(), name='save-vote'),
]
models.py
class Answer(VoteModel, models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
detail = models.TextField()
add_time = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return f"/questions/"
def __str__(self):
return self.detail
In AnswerForm you get all url parameters added to self because of base class DetailedView. In your case "self.pk". You can then add anything to the context for the html rendering by implementing get_context_data:
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in the publisher
context['question_pk'] = self.pk
return context
See https://docs.djangoproject.com/en/4.0/topics/class-based-views/generic-display/

Django views.py add multiple files

I have a model.py in which I would like to upload multiple files. In my models I have main class and another which I'm trying to use to upload multiple file as suggested. Problem is, I get the following error in my class in views.py 'Exception Value: Unknown field(s) (file) specified for Post' and I can't get it to upload multiple files.
model.py
class Post(models.Model):
title = models.CharField(max_length=40, verbose_name="Naslov predmeta")
# a lot more field here but not important
file_1 = models.FileField(blank=True, upload_to='PN_datoteke/%Y/%m/%d/', verbose_name="Datoteka 1", validators=[validate_file_size])
file_2 = models.FileField(blank=True, upload_to='PN_datoteke/%Y/%m/%d/', verbose_name="Datoteka 2", validators=[validate_file_size])
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk':self.pk})
class File(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
file = models.FileField(blank=True, upload_to='PN_datoteke/%Y/%m/%d/', verbose_name="Datoteke", validators=[validate_file_size])
views.py
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content_don', 'subject', 'rn_number', 'file_1', 'file_2']
def form_valid(self, form):
form.instance.author = self.request.user
#here I have a lot of code to process data which is writen in the fields
response = super(PostCreateView,self).form_valid(form)
#################################################################
##### this code below I'm trying to use to upload multiple files
obj = form.save(commit=False)
if self.request.FILES:
for f in self.request.FILES.getlist('file'):
obj = self.model.objects.create(file=f)
return response
I also tried using forms, but I can't get my scripts/querys and simmilar to work then. Is there a way to add file from class File in models to my views.py class and then use it to upload multiple fiels? Or is there a easier way?
forms.py
from django import forms
from .models import Post, File
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content_don', 'subject', 'rn_number', 'report_division', 'report_department', 'nc_type', 'number_res_people', 'res_person_1', 'res_person_2', 'res_person_3', 'res_person_4', 'urgency',
'date_days', 'cost_pn', 'cost_pn_tip', 'reklamacija', 'file_1', 'file_2', 'file_3', 'file_4']
class PostFileForm(PostForm): #extending form
file = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta(PostForm.Meta):
fields = PostForm.Meta.fields + ['file',]
html template has a script to add multiple files upload option to my field, I'm not using widgets in forms.
<script>
$(document).ready(function(){
$('#id_file_1').attr("multiple","true");
})
</script>

I have a problem in user redirecting in django

I am a beginner and I am creating a forum using html, css, bootstrap, python and django. I created a view for deleting posts:
class DeletePost(DeleteView):
model = Post
success_url = '/'
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(author_post_id=self.request.user.id)
When a user will click the "Confirm button", when he need to remove a post, i would like to redirect him to the same discussion's page in which there was the post that he deleted, but i don't know how.
Can somebody help? Thanks in advance.
Post model:
class Post(models.Model):
post_author = ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
content = models.TextField(default="Your content here...")
creation_date = DateTimeField(auto_now_add=True)
discussion = ForeignKey(Discussion, on_delete=models.CASCADE)
def __str__(self):
return self.post_author.username
class Meta:
verbose_name = 'Post'
verbose_name_plural = 'Posts'
Urls:
Discussion's url:
path('discussion/<int:pk>', views.view_discussion, name='view_discussion')
DeleteView's url:
path('discussion/<int:id>/delete_post/<int:pk>/', views.DeletePost.as_view(), name='delete_post')
You can override the get_success_url with:
class DeletePost(DeleteView):
model = Post
def get_queryset(self):
return super().get_queryset().filter(
author_post_id=self.request.user.id
)
def get_success_url(self):
return reverse('view_discussion', kwargs={'pk': self.object.discussion_id})
You can use the 'redirect' method in Django.
First import it: from django.shortcuts import redirect
then write this one line of code : return redirect('/nameOfURL') under your class/function based views.
Update :
def delete_post(request, id):
if request.method == 'POST':
pi = Post.objects.get(pk=id)
pi.delete()
return redirect('/view_discussion')

How to retrieve all the comments for a post using related names?

I am trying to create a comment page for a blog-style site that will list all of the previous comments for a single related post.
I am having trouble figuring out how to structure the view to get what I'm looking for. I have been trying to use related names to get the data but am not sure if that is the right method.
Here are my models:
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=128)
content = models.TextField()
image = models.ImageField(upload_to='post_pics', blank=True)
date_posted = models.DateTimeField(default=timezone.now)
def get_absolute_url(self):
return reverse('home')
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.TextField()
date_created = models.DateTimeField(default=timezone.now)
def get_absolute_url(self):
return reverse('home')
And here is my view:
class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
template_name = 'home/comment-form.html'
fields = ['comment',]
def get_context_data(self, **kwargs):
context = super(CommentCreateView, self).get_context_data(**kwargs)
context['post'] = Post.objects.get(pk=self.kwargs['pk'])
comments = Post.comments.all()
context['comments'] = comments
return context
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = Post.objects.get(pk=self.kwargs['pk'])
return super().form_valid(form)
I have been trying a bunch of different things. The above is just my latest attempt. When I try to run this one I get a 'ReverseManyToOneDescriptor' object has no attribute 'all' error.
I don't know if I need to run a get_queryset() function or maybe call a queryset at the beginning of the view?
Know this is probably a very basic issue but I appreciate the help!
You do not need to pass comments to template, you can simply use:
{% for comment in post.comments.all %}
{{ comment.comment }}
{% endfor %}
It is possible because you already defined related_name='comments' in Comment model.
To get the comments, you can use a filter()
Class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
template_name = 'home/comment-form.html'
fields = ['comment',]
def get_context_data(self, **kwargs):
context = super(CommentCreateView, self).get_context_data(**kwargs)
post = Post.objects.get(pk=self.kwargs['pk'])
context['post'] = post
comments = Comment.objects.filter(post=post)
context['comments'] = comments
return context

I can't get return super().form_valid(form) to work

I have resolved my issue and provided my solution below.
When I create or update a post the changes are saved to the sites database. But after clicking the submit button I get an error message.
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
I want to be redirected to the current URL. I thought the line of code return super().form_valid(form) implied that.
I could do success_url = '/'but I ideally don't want to be returned to the homepage.
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
The code in models.py was wrong, I was missing indents.
My site runs fine with this code -
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})

Categories

Resources