I have a view that renders a comment form along with a template:
views.py
def news(request):
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = Article.objects.get(pk=2)
print(comment.post)
comment.author = request.user.username
comment.save()
return HttpResponseRedirect('')
else:
form = CommentForm()
return render(request, '../templates/news.html', context={"form": form})
models.py
class Comment(models.Model):
post = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments', blank=True)
author = models.TextField()
text = models.TextField()
def __str__(self):
return self.text
forms.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('text',)
In views.py, where comment.post is getting assigned to Article objects, I want the pk to be applied dynamically. I tried doing it in the templates, where putting {{ article.pk }} in the templates output the right pk for the Article object but I wasn't sure how I'd go about applying it to my form.
The templates look simple: Article object, below it a comment form.
The problem is simple, I want the news(request) function to dynamically apply the pk of the current Article object in order to make the comment go to the right post.
You can either use the path if it's unique or you can just add a hidden field and set the article pk as value:
<input name="post" type="hidden" value={{ article.pk }} />
And your form:
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('text', 'post')
and you can access it from validated data in view.
Related
My Objective
Access the field name in the Parent Model ParentModel and display its content in a form instance in the template. For example, let the field parent be a foreign key in the ChildModel as described below.
What I have tried
Access the parent field in the form as {{ form.parent.name }} in the template
Errors received
Tried looking up form.parent.name in context
models.py
class ParentModel(models.Model):
name = models.CharField()
def __str__(self):
return self.name
class ChildModel(models.Model):
parent = models.ForeignKey(ParentModel)
def __str__(self):
return self.parent.name
forms.py
class ChildModelForm(ModelForm):
class Meta:
model = ChildModel
fields = '__all__'
widgets = {'parent': forms.Select(),}
views.py
def childView(request, pk):
template = 'template.html'
child = ChildModel.objects.get(parent=pk)
form = ChildModelForm(instance=child)
if request.method == 'POST':
form = ChildModelForm(request.POST, instance=child)
if form.is_valid():
form.save()
else:
form = ChildModelForm(instance=child)
context = {'form': form, }
return render(request, template, context)
template.html
<form method="POST" action="">
{% csrf_token %}
{{form.parent.name}}
<button type="submit">Save</button>
</form>
Now the child model form displays pk I want to display the name of the parent field
I have also tried using this Django access foreignkey fields in a form but it did not work for me.
From my understanding, you want to display the form instance's values. You can do:
form.instance.parent.name
I'm creating a form where if we register it should save data to the database if the form is valid. otherwise, it should raise an error but it doesn't save data to the database, and also some fields are required but if I submit the form it doesn't even raise the error field is required. but if I register it manually on Django admin pannel it works perfectly fine.
here is my model:
class foodlancer(models.Model):
Your_Name = models.CharField(max_length=50)
Kitchen_Name = models.CharField(max_length=50)
Email_Address = models.EmailField(max_length=50)
Street_Address = models.CharField(max_length=50)
City = models.CharField(max_length=5)
phone = PhoneNumberField(null=False, blank=False, unique=True)
def __str__(self):
return f'{self.Your_Name}'
also, I disabled html5 validation
forms.py
class FoodlancerRegistration(forms.ModelForm):
phone = forms.CharField(widget=PhoneNumberPrefixWidget(initial="US"))
class Meta:
model = foodlancer
fields = "__all__"
views.py:
def apply_foodlancer(request):
form = FoodlancerRegistration()
return render(request, 'appy_foodlancer.html', {"form": form})
and finally Django template
<form method="POST" novalidate>
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="cta-btn cta-btn-primary">Submit</button>
</form>
Thank you for your time/help
You don't have any form saving logic in your view.
Try something like this:
def apply_foodlancer(request):
if request.method == 'POST':
form = FoodlancerRegistration(data=request.POST)
if form.is_valid(): # if it's not valid, error messages are shown in the form
form.save()
# redirect to some successpage or so
return HttpResponse("<h1>Success!</h1>")
else:
# make sure to present a new form when called with GET
form = FoodlancerRegistration()
return render(request, 'appy_foodlancer.html', {"form": form})
Also check that the method of your form in your HTML file is post. I'm not sure if POST also works.
Avoid defining fields in a modelform with __all__. It's less secure, as written in the docs
Basically I want to create a comment model section like youtube, Instagram, in which we can add comment/body in a detailed view of a post or video, and username which will be posted automatically from request.
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comment_by')
email = models.EmailField()
body = models.TextField(help_text='Add a comment')
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.name} on {self.post}'
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['email', 'body']
views.py
class PostDetailView(DetailView):
model = Post
# display comments and comment_form
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
qs = Comment.objects.filter(post=self.kwargs.get('pk'), active=True)
context['comments'] = qs.order_by('-created', '-updated')
context['comment_form'] = CommentForm() # adding empty form
return context
class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
form_class = CommentForm
template_name = 'blog/post_detail.html'
success_url = reverse_lazy('post-detail')
new_comment = None
def form_valid(self, form):
post = self.get_object()
form.instance.post = post
form.instance.name = self.request.user
return super().form_valid(form)
I have post and comment models. I want to add a comment form in the post detail view. I'm able to add empty form but unable to post/add comments. When I submit the form with data in it, it shows this error: This page isn’t working. If the problem continues, contact the site owner. HTTP ERROR 405 PostDetailView works fine but doesn't know how to get working CommentCreateView in correct way. I've just started with class-based views. Thanks in advance.
You need to point the action="{% url 'create_comment %}" for the comment form to the correct view.
But replacing {% url 'create_comment %} with the URL path that points to the CommentCreateView view.
example: template.html
<form action="{% url 'create_comment %}" method="POST">
{% csrf_token %}
{{ comment_form }}
</form>
Have you solved your issue? I had the same problem and I solved by doing form.save() inside the form_valid method.
I have the basics of a blogs app (I have been following Corey Schafer's tutorial, part 10, if that matters) and I am trying to post and display comments on the post that other users have wrote that only relate to that post. Similar to that of a comment section on Facebook or YouTube.
Currently I'm displaying all comments in the database on every post because I don't know how to filter the results to only show comments for the specific post and I also don't know how to post comments to a specific post, that's where I get the error.
My code is below:
Models.py
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('core:post-detail', kwargs={'pk': self.pk})
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.user.username
Views.py
class PostDetailView(DetailView):
model = Post
context_object_name = 'posts'
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
context['comment'] = Comment.objects.all()
return context
class CommentCreateView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['content']
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
urls.py (This is the urls.py file in my main app where I'm calling the blogs app views)
path('posts/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('posts/<int:pk>/comment', CommentCreateView.as_view(), name='comment-create'),
I then have this form in a file called comment_form.html that I can connect to when I got to http://127.0.0.1:8000/posts/5/comment but when I click reply I get
IntegrityError at /posts/5/comment NOT NULL constraint failed: posts_comment.post_id
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Reply to Post </legend>
{{ form|crispy}}
</fieldset>
<div class="form-group">.
<button type="submit" class="btn btn-success">Reply</button>
</div>
</form>
If someone could throw their eye over it and let me know if you can find anything that I could do to get it to work, I would greatly appreciate it. Let me know if you need more information/code.
Thanks
the problem is that you're creation form is missing a non nullable field, that's why django is complaining about the "NOT NULL CONSTRAINT"
so you have to add the post field to the form fields, or you can add it in the form_valid method:
def form_valid(self, form):
form.instance.post = Post.objects.get(pk=self.kwargs.get("pk"))
form.instance.user = self.request.user
return super().form_valid(form)
if you want to ignore the post field, you can put null=True in the Comment Model:
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post,null=True,blank=True,on_delete=models.CASCADE)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
I created a Form using one of my models i.e (Post), for my blog website. The form is meant for writers to post articles. In that form there is an Image attribute where the writer can upload an image. However, when i try to upload an image and post it, i get a feedback saying "field required", i think the form is not recognizing the image am trying to upload onto the the database. please help:
this is the form view from views.py:
def formview(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return render(request, 'form.html', {'form':form})
this is from forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
image = forms.FileField
class Meta:
model = Post
fields = ['category', 'title', 'body', 'image', 'author']
this from my models.py:
class Post(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=100)
pub_date = models.DateTimeField(auto_now_add=True)
body = models.TextField()
image = models.FileField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.IntegerField(default=1)
def __str__(self):
return self.title
this is my forms.html template:
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Post</button>
this is my urls.py:
from django.conf.urls import url
from . import views
app_name = 'posts'
urlpatterns = [
url(r'^$', views.homeview, name='homeview'),
url(r'^(?P<pk>[0-9]+)$', views.postview, name='postview'),
url(r'^category/(?P<pk>[a-zA-Z0-9]+)/$', views.categoryview,
name='categoryview'),
url(r'^author/(?P<pk>[a-zA-Z0-9]+)/$', views.authorview, name='authorview'),
url(r'^add_post/$', views.formview, name='formview'),
]
these are the pics might help explain what am trying to say:
Filling the form and selecting the picture
Error message after trying to post
Thank you
def formview(request):
if request.method == 'POST':
form = PostForm(request.POST,request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
else:
form = PostForm()
return render(request, 'form.html', {'form':form})
this form = PostForm(request.POST,request.FILES),you need add FILES to PostForm