I am developing a blog which i want to add comment form option to it, i have added the form to the same page directly under the article, i want that went a user comment it should redirect to the same page with the article but i keep getting and error
here is my code
view
def comment(request, article_id):
try:
article = Article.objects.get(pk=article_id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.cleaned_data['comment']
article.comments_set.create(comment=comment)
#messages.infos(request,comment)
return redirect('blog:_article')
#else:
#pass
#form = CommentForm()
#context['form'] = form
#return render(request,'blog/comment.html', context)
except Exception as e:
#wriet error to file
return render(request,'blog/404.html')
urls
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.index, name='index'),
path('<int:article_id>/article', views._article, name='_article'),
path('<int:article_id>/comment', views.comment, name='comment'),
]
models
class Comments(models.Model):
comment = models.TextField()
date = models.DateTimeField(default=timezone.now)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
def __str__(self):
return self.comment
form
<form method="post" action="{% url 'blog:comment' article.id %}">
{% csrf_token %}
{% for field in form %}
{{ field.label_tag }}
{% render_field field class="form-control is-valid" rows="4" %}
{% endfor %}<br>
<button class="btn btn-success">Post</button>
</form>
I finally did it by adding the code to handle the comment in the same view that renders the articles this is my code
def _article(request, article_id):
try:
article = Article.objects.get(pk=article_id)
related_articles = Article.objects.filter(tags=article.tags).exclude(pk=article.pk)[:4]
context['article'] = article
context['related_articles'] = related_articles
context['form'] = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.cleaned_data['comment']
article.comments_set.create(comment=comment)
return render(request,'blog/article.html', context)
except Exception as e:
#write error to file
return render(request,'blog/404.html')
If you don't want the page to redirect to another page or update the page, you should use AJAX (https://www.w3schools.com/jquery/jquery_ajax_get_post.asp) in this case. Your form will hit the url in the action by changing your page to that url so you have to handle the redirecting and rendering in your commenting view to come back to same page if you don't wanna do this dynamically.
Related
I am going through a Django tutorial and My blog post image is not editing for edit post in my blog app. I use Django==3.1.2.
views.py
def edit_post(request, post_id):
post = BlogPost.objects.get(id=post_id)
if request.method != 'POST':
form = UpdatePost(request.POST or None, request.FILES or None, instance=post)
else:
form = UpdatePost(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('mains:posts')
context = {'post':post,'form':form}
return render(request, 'mains/edit_post.html', context)
forms.py
class UpdatePost(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['blog_post_title','blog_description','image']
edit_post.html
{% block content %}
<div class="container">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Save Changes</button>
</form>
</div>
{% endblock content %}
The Problem
I am trying to edit my post in my blog app, Everything is working fine ( Blog title and Blog description is changing ) - when i change image it returns ( redirect ) fine BUT image not changing.
I am stuck with this problem and have no idea what is wrong.
What have i tried.
1). When i first create the view then i didn't add (request.POST or None, request.FILES or None), BUT
when i notice that, this may be effecting from editing then i added and it still not editing the image.
2). I have also changed template before BUT nothing works.
3). I have also changed form before BUT nothing workes.
Help me in this. I will really appreciate your Help. Thank you in advance !!
try this...
def edit_post(request, post_id):
post = BlogPost.objects.get(id=post_id)
if request.method != 'POST':
form = UpdatePost(request.POST or None, request.FILES or None, instance=post)
else:
form = UpdatePost(instance=post, data=request.POST, files=request.FILES)
if form.is_valid():
form.save()
return redirect('mains:posts')
context = {'post':post,'form':form}
return render(request, 'mains/edit_post.html', context)
So the title kind of says it all. I have a form based on a model. The goal is to have the specific data entered, user presses submit, data gets saved to a Postgresql DB, user sees complete.html. However this is not the case. I can either get the data to save without changing pages, or the page will change but the data will not submit. I have put details on the specifics of I tried below.
urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.index, name='index-page'),
path('feedback/', views.feedback_view, name = 'feedback'),
path('complete/', views.complete, name = 'complete')
]
models.py
from django.db import models
from django.utils import timezone
from django.core.validators import RegexValidator
class feedback(models.Model):
RECENT_GROUND = [
('PVT','Private'),
('INS','Instrument'),
('COM','Commercial'),
('MEL','Multi-Engine'),
]
RATING = [
(1,'Poor'),
(2,'Below Average'),
(3,'Average'),
(4,'Above Average'),
(5,'Excellent'),
]
id_field = models.AutoField(primary_key = True, serialize = True)
added = models.DateTimeField(default = timezone.now)
spid = models.CharField(primary_key = False, max_length=5, verbose_name = 'Enter the students FSA ID number:')
recent_ground = models.CharField(max_length = 3, choices = RECENT_GROUND, verbose_name = 'Most recently completed ground school:')
question1 = models.IntegerField(choices = RATING, verbose_name = 'This is question 1')
question2 = models.IntegerField(choices = RATING, verbose_name = 'This is question 2')
question3 = models.IntegerField(choices = RATING, verbose_name = 'This is question 3')
question4 = models.IntegerField(choices = RATING, verbose_name = 'This is question 4')
question5 = models.IntegerField(choices = RATING, verbose_name = 'This is question 5')
question6 = models.IntegerField(choices = RATING, verbose_name = 'This is question 6')
question7 = models.IntegerField(choices = RATING, verbose_name = 'This is question 7')
comments = models.TextField(max_length = 500, verbose_name = 'Please leave any additional comments below. If you do not wish to leave comments, type "none".')
def __str__(self):
return self.title
forms.py
#imports forms class from django
from django import forms
#imports the feedback class from ipfeedbackdb/models.py
from ipfeedbackdb.models import feedback
class feedbackForm(forms.ModelForm):
class Meta:
model = feedback
fields = "__all__"
exclude = ['recID','added']
views.py
from django.shortcuts import render
from .forms import feedbackForm as feedform
def index(request):
return render(request, 'index/index.html', {'title':' Home'})
# def feedback(request):
# return render(request, 'index/feedback.html', {'title':' Collection'})
def feedback_view(request):
context = {}
form = feedform(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
context['form'] = form
return render(request, "index/feedback.html", context)
def complete(request):
return render(request, 'index/complete.html', {'title':' Submitted'})
base.html (removed most of the styling to reduce length)
{% load static %}
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="{% static 'index/override.css' %}">
{% if title %}
<title>Feedback{{ title }}</title>
{% else %}
<title>Feedback Site</title>
{% endif %}
<script type="text/javascript">
window.history.forward();
function noBack() { window.history.forward(); }
</script>
</head>
<body onload="noBack();" onpageshow="if (event.persisted) noBack();" onunload="">
<div class = 'jumbotron jumbotron-fluid'>
<div class = 'container'>
<h2 class = 'display-4' style = 'color:#fff;margin-left: -100px'>FSA</h2>
<p class = 'lead' style = 'color:#fff;;margin-left: -97px'>Feedback</p>
</div>
</div>
<div>
{% block content %}
{% endblock content %}
</div>
</body>
</html>
index.html
{% extends 'index/base.html' %}
{% block content %}
<div>
<h2>Index Page</h2>
<p>This is some more added text.</p>
</div>
<div>
Next ->
</div>
{% endblock content %}
feedback.html (action = "" saves data without changing pages or clearing form, action ="/feedback/" will save but not clear the form or go to another page. action = "/complete/" took me to complete.html but it did not submit the data to the database.)
{% extends 'index/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div>
<h2>Feedback Form Page</h1>
</div>
<div>
<form action = "" method = "post">
{% csrf_token %}
{{ form| crispy }}
<input type="submit" name="Submit">
</form>
</div>
{% endblock content %}
complete.html
{% extends 'index/base.html' %}
{% block content %}
<h2>Your feedback has been submitted. Thank you!</h2>
<div>
Return to start
</div>
{% endblock content %}
In your feedback view, once forms is valid it doesn't go to complete.
def feedback_view(request):
context = {}
form = feedform(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
return render(request, "index/complete.html", context)
else:
context['form'] = form
return render(request, "index/feedback.html", context)
use button tag!
replace:
<button type="submit">submit</button>
with:
<input type="submit" name="Submit">
change your view like below
views.py:
from django.contrib import messages
from django.shortcuts import redirect
def feedback_view(request):
context = {}
form = feedform(request.POST or None, request.FILES or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect('app_name:url_name') # change to where you want to redirect after a successful from submition
messages.success(request, "Form submitted successfully")
else:
messages.warning(request, form.errors)
context['form'] = form
return render(request, "index/feedback.html", context)
So I'm trying to do a logout link in my Django app. I've set a view that logs out the user and then redirects him to a template paginaPrincinal.html that has two buttons for login and register.
The problem is that for some reason the link href that I'm creating in my index.html doesn't appear.
my views.py
def login_view(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect('index')
else:
form = AuthenticationForm()
return render(request, 'registration/login.html', {'form': form})
def logout_view(request):
logout(request)
return redirect('paginaPrincipal')
my urls.py
path('principal/', views.intro, name='pagina_principal'),
path('registro/', views.registro_usuario, name='registro_usuario'),
path('login/', views.login_view, name="login"),
path('logout/', views.logout_view, name="logout"),
path('',views.index, name ='index'),
index.html
{% block contenido %}
<div>
<ul>
{% if user.is_authenticated %}
<li>Hola, {{user.username}}</li>
<li></li>
{% endif %}
</ul>
</div>
{% endblock %}
The error that appears if I inspect the code and try to go to the Href is this:
NoReverseMatch at /myapp2/logout/
Reverse for 'paginaPrincipal' not found. 'paginaPrincipal' is not a valid view function or pattern name.
The string you pass into redirect should be a url route name. The problem is that 'paginaPrincipal' != 'pagina_principal'
def logout_view(request):
logout(request)
return redirect('pagina_principal')
That should fix it.
You are redirecting to "paginaPrincipal", but you have defined "pagina_principal". You have to change your view function
def logout_view(request):
logout(request)
return redirect('pagina_principal')
NoReverseMatch Means you have to set app_name in the urls.py like
app_name= "app_name"
and in the templates
it should work
I have made this HTML code:
<h3>your major is {{user.userprofile.major}}</h3>
This will correctly show the major on the webpage, but I want to use this string to get something from another table in view.
How would I pass this string to view?
edit:
Here is my view.py
def dashboardView(request):
obj = BooksFile.objects.all()
query = BooksFile.objects.filter(book_major='cs)
return render(request, 'dashboard.html', {'books': obj, 'major': query})
def registerView(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST)
if form.is_valid() and profile_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return redirect('login_url')
else:
form = UserCreationForm()
profile_form = UserProfileForm()
context = {'form': form, 'profile_form': profile_form}
return render(request, 'registration/register.html', context)
here is my template:
{% extends 'index.html' %}
{% block content %}
<h1>Welcome, {{user.username}}</h1>
<h2>Your major is {{user.userprofile.major}}</h2>
{% for book in books %}
<h3>Your book name is {{book.book_name}}</h3>
{% endfor %}
{% endblock %}
I am trying to show the book names from the booksfile table by corresponding major that user has. Right its showing the books that has "cs" attribute because I manually put "cs" in the get function in view. I am trying to send the major string from template to view, so that I can put what ever the user's major is in the get function. Or is there any other way to do it.
You need to use a form in your template and submit it to call your view. i.e.
<form action="your_view_url" method="POST">
<input type="text" name="major" value="{{user.userprofile.major}}"/>
<input type="submit"/>
</form>
an then in your view you access that with:
if request.POST:
major = request.POST.get('major')
As per documentation: https://docs.djangoproject.com/en/2.2/topics/forms/
First of all you have to get the value of model with help of queryset, and put it in the dictionary and then pass it with the template.
In views:
def get(self, request):
queryset = Model_name.objects.all()
ctx = {
'queryset': queryset,
}
return render(request, 'page_name(or template_name).html', ctx)
in template:
<form action="{%url'(your_view_name without brackets)'%}" method="POST">
{% for data in queryset%}
<span class="username">{{data.name(field of your model)}} .
</span>
<span class="email">{{data.email(field of your model)}} .
</span>
{% endfor%}
</form>
The form field (text area) is not showing in my django template. I can figure out where the problem is.
Views.py
class Profile(View):
"""User Profile page reachable from /user/<username> URL"""
def get(self, request, username):
params = dict()
user = User.objects.get(username=username)
tweets = Tweet.objects.filter(user=user)
params["tweets"] = tweets
params["user"] = user
return render(request, 'profile.html', params)
class PostTweet(View):
"""Tweet Post form available on page /user/<username> URL"""
def post(self, request, username):
if request.method == 'GET':
form = TweettForm()
else:
form = TweetForm(self.request.POST)
if form.is_valid():
user = User.objects.get(username=username)
tweet = Tweet(text=form.cleaned_data['text'], user=user, country=form.cleaned_data['country'])
tweet.save()
words = form.cleaned_data['text'].split(" ")
for word in words:
if word[0] == "#":
hashtag, created = HashTag.objects.get_or_create(name=word[1:])
hashtag.tweet.add(tweet)
return HttpResponseRedirect('/user/'+username)
return render(request, 'profile.html', {'form': form})
forms.py
from django import forms
class TweetForm(forms.Form):
text = forms.CharField(widget=forms.Textarea(attrs={'rows': 1, 'cols':85}), max_length=160)
country = forms.CharField(widget=forms.HiddenInput())
profile.html
{% extends "base.html" %}
{% block content %}
<div class="row clearfix">
<div class="col-md-12 column">
<form method="post" action="post/">{% csrf_token %}
<div class="col-md-8 col-md-offset-2 fieldWrapper">
{{ form.text.errors }}
{{ form.text }}
</div>
{{ form.country.as_hidden }}
<div>
<input type="submit" value="post">
</div>
</form>
</div>
urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from tweets.views import Index, Profile, PostTweet
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', Index.as_view()),
url(r'^user/(\w+)/$', Profile.as_view()),
url(r'^admin/', include(admin.site.urls)),
url(r'^user/(\w+)/post/$', PostTweet.as_view())
)
Only the submit (post) button shows on the on when rendered in the browser. The text are is not there
You get nothing since you are not passing the form to the template. Write get function in PostTweet view and include form = TweetForm() in it as a param passed to the template.