Django form does not save new post using based view function - python

I have a model as follow:
class Post(models.Model):
title = models.CharField(max_length=150)
author = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
imagefile = models.FileField(null=True, blank=True, upload_to='images', default='default.jpg')
There is a bug in the view file that, when I use class base view I can post the new post but whenever I use it as a function it does not save the form.
This one works(saves post in database):
class PostCreateView(LoginRequiredMixin, AjaxFormMixin, CreateView):
model = Post
template_name = "app/postform.html"
success_url = '/posts'
form_class = postform
But this one does not(does not save post in database):
#login_required
def PostCreateView(request):
if request.method == 'POST':
mform = postform(request.POST or None, request.FILES or None, instance=request.user)
if mform.is_valid():
mform.save() # when I print something here, Ill see something
messages.success(request, f'Yes!')
return redirect('posts')
else:
mform = postform()
return render(request, 'myapplication/postform.html', {'form': mform})
and in postform.html:
<form method="POST" action="" enctype="multipart/form-data">
<fieldset class="form-group">
{% csrf_token %}
<div class="content-section">
<!-- {{ form|crispy }} -->
</div>
</fieldset>
</form>
and form.py:
class postform(forms.ModelForm):
class Meta:
model = Post
fields = ("__all__")
exclude = ['date_posted']

I think the problem is that you form's model is post and you're assigning object of user as instance.
So try this way:
#login_required
def PostCreateView(request):
if request.method == 'POST':
mform = postform(request.POST or None, request.FILES or None)
if mform.is_valid():
post = mform.save(commit=False)
post.author = request.user
post.save()
messages.success(request, f'Yes!')
return redirect('posts')
else:
mform = postform()
return render(request, 'myapplication/postform.html', {'form': mform})

Related

Django dose not validate form

I have form with the name of CommentForm when the form is validated it has to return HttpResponse which is saying that the form is valid if does nothing
views.py
def comment(request,pk):
blog = BlogPost.objects.get(pk=pk)
comment = CommentForm()
if request.method == "POST":
comment = CommentForm(request.POST or None)
if comment.is_valid():
return HttpResponse('this is request method')
context = {
'blog':blog,
'comment':comment,
}
return render(request, 'blog/comment.html', context)
froms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = '__all__'
models.py
class Comment(models.Model):
blog = models.ForeignKey('BlogPost', on_delete = models.CASCADE)
text = models.TextField()
template
{% extends 'base.html' %}
{% block content %}
{{blog.title}}
<form method="POST" action="">
{% csrf_token %}
{{comment.text}}
<input type="submit">
<form>
{% endblock %}
I used class meta in my forms.py I removed class meta and I save comments to model while instantiating it in view.py.
form.py
class CommentForm(forms.Form):
text = forms.CharField(widget=forms.Textarea())
view.py
def comment(request,pk):
blog = BlogPost.objects.get(id=pk)
form = CommentForm()
if request.method=='POST':
form = CommentForm(request.POST)
if form.is_valid():
comments = Comment(
text = form.cleaned_data['text'],
blog =blog
)
comments.save()
return redirect('/blog')
else:
context = {'blog':blog,
'form':form}
return render(request, 'blog/comment.html', context)

django ModelForm extra field

i will like to have extra field in modelForm. From this extra field i will like to pass the value to field in model when save. this is example what i want to get
will like to generate name in random name field, and save to database as name
models.py
from django.db import models
class Test2App(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
forms.py
from django import forms
from .models import test2App
class TestForm(forms.ModelForm):
class Meta:
model = Test2App
fields = ['name']
Views.py
def add_name(request):
if request.method == 'POST':
form = TestForm(request.POST)
if form.is_valid():
form.save()
return redirect('test_name')
else:
form = TestForm()
return render(request, 'test/add.html', {'form': form})
html
<form method="post">
{% csrf_token %}
<label for="name">Random Name</label>
<button>Generate</button>
<input id="name" name="name_test">
{{ form}}
<input type="submit" value="Submit">
</form>
def add_name(request):
if request.method == 'POST':
form = TestForm(request.POST)
name1 = request.POST.get('name_test')
print(name1)
if form.is_valid():
form.instance.name = name1
form.save()
return redirect('test_name')
else:
form = TestForm()
return render(request, 'test/add.html', {'form': form})

How to make the post title available at my template

i need to know how i can make the actual postname a comment belongs to available at my template to display it later on:
views.py
def comment_edit(request, pk):
comment = get_object_or_404(Comment, pk=pk)
if request.user == comment.author:
if request.method == "POST":
form = CommentForm(request.POST, instance=comment)
if form.is_valid():
comment = form.save(commit=False)
comment.author = request.user
comment.published_date = timezone.now()
comment.save()
return redirect('post_detail', pk=comment.post.pk)
else:
form = CommentForm(instance=comment)
return render(request, 'app/Post/post_comment_edit.html', {'form': form})
else:
return redirect('post_detail', pk=comment.post.pk)
template.html:
{{ post.category.title }}
{{ post.title }}
models.py
class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField(max_length=500)
published_date = models.DateField(auto_now_add=True, null=True)
thanks in advance
pass the comment instance to your template
return render(request, 'app/Post/post_comment_edit.html', {'form': form, 'comment': comment})
and in template
{{ comment.post.category.title }}
{{ comment.post.title }}

How to add a comment to post? PostDetailVew, Django 2.1.5

I want add comment to post on his page ("post detail" page).
I was find answer, but it create comment on other page. I want create comment on page of "post detail".
urls.py
url(r'^post/(?P<pk>\d+)/create/$', views.CommentCreate.as_view(), name='comment_create'),
models.py
class Comment(models.Model):
description = RichTextUploadingField()
author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
comment_date = models.DateTimeField(auto_now_add=True, null=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
class Meta:
ordering = ["-comment_date"]
def __str__(self):
return "{}".format(self.description)
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['description']
views.py
class PostDetailView(generic.DetailView):
model = Post
class CommentCreate(LoginRequiredMixin, CreateView):
model = Comment
fields = ['description']
def get_context_data(self, **kwargs):
context = super(CommentCreate, self).get_context_data(**kwargs)
context['post'] = get_object_or_404(Post, pk = self.kwargs['pk'])
return context
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.post=get_object_or_404(Post, pk = self.kwargs['pk'])
return super(CommentCreate, self).form_valid(form)
def get_success_url(self):
return reverse('post-detail', kwargs={'pk': self.kwargs['pk'],})
comment_form.html
...
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Submit</button>
</form>
...
post_detail.html
...
{% for comment in post.comment_set.all %}
<p>{{ comment.author }} ({{ comment.comment_date }}) {{ comment.description|safe }}</p>
{% endfor %}
<hr>
{% if user.is_authenticated %}
<p>Add a new comment</p>
...
I think, "comment_form" need to redirect to "post_detail", not generate new page for comment form.
And сould you tell, which parameters has a RichTextField (CKE), how change width, height field only in comment?
If you want the comment form right in your detail page then all you have to do is to add the form and post function in your View,
class PostDetailView(DetailView):
model = Post
template_name = 'yourdetailpage.html'
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
context['commentform'] = CommentForm()
return context
def post(self, request, pk):
post = get_object_or_404(Post, pk=pk)
form = CommentForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.post = post
obj.author = self.request.user
obj.save()
return redirect('detail', post.pk)
And now you can add your form in your html. And add a submit button to post comment.

How do i get user profile in django 1.7

I want to fetch each and every detail of user profile. I know function get_profile() has been depreciated.
I want get user profile and then pass it as context to template.
Actually I am making a "Edit user profile" functionality.
My Model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
state = models.CharField(max_length=200, blank=True)
country = models.CharField(max_length=200, blank=True)
zipcode = models.CharField(max_length=200, blank=True)
And views:
#login_required
def dashboard(request):
context = RequestContext(request)
profile = request.user.userprofile
context_dict = {'profile': profile}
return render_to_response('appname/dashboard.html', context_dict, context)
To edit both User and Profile instance you have to use two forms:
class UserForm(forms.ModelForm):
class Meta:
class = User
fields = ('username', 'first_name', 'last_name')
class ProfileForm(forms.ModelForm):
class Meta:
class = UserProfile
exclude = ('user', )
#login_required
def edit_profile(request):
user = request.user
profile = user.userprofile
if request.method == 'POST':
user_form = UserForm(request.POST, instance=user)
profile_form = ProfileForm(request.POST, instance=profile)
if all([user_form.is_valid(), profile_form.is_valid()]):
user_form.save()
profile_form.save()
return redirect('.')
else:
user_form = UserForm(instance=user)
profile_form = ProfileForm(instance=profile)
return render(request, 'user_profile.html',
{'user_form': user_form, 'profile_form': profile_form})
And the template should contain both forms in the single <form> tag:
<form action="." method="POST">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<button>Update</button>
</form>

Categories