I'm trying to create comments for a django blog project, but the form submission button does not doing anything when clicked.
Here is the html for the template.
<form role="form" method="post">
<div class="input-group">
{% csrf_token %}
{% for field in form %}
{{ field }}
{% endfor %}
<p>Comment: </p>
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Submit</button>
</span>
</div>
</form>
Here is the view I'm trying to call when I press the button.
def detail(request, slug):
context ={}
post = BlogPost.objects.get(slug=slug)
# print(request.method)
if request.method=='POST':
form = CommentForm(request.POST)
else:
form = CommentForm()
if form.is_valid():
t = form.save(commit=False)
t.commentTime = datetime.datetime.now()
t.save()
return HttpResponseRedirect(reverse('blogpost_detail'))
comment_list=Comments.objects.order_by('-commentTime')[:25]
context = {'comment':comment_list,'form':form, 'post': post}
return render(request, 'blog/blogpost_detail.html', context)
And here is the form that is called in the template.
class CommentForm(forms.ModelForm):
class Meta:
model = Comments
fields=('commentText', 'commentImage',)
exclude =('post','commentTime',)
widgets={
'commentText': forms.Textarea(attrs={'col':10}),
}
Thanks for the help!
You need an action attribute in the form tag. Since you're posting to the same URL, it should be
<form action="." method="post " roleĀ°"form">
Related
This is my forms.
class CreateBooksForm(forms.ModelForm):
languages = forms.CharField(widget=forms.TextInput)
file = forms.FileField(widget=forms.FileInput(attrs={'accept':'application/pdf'}))
class Meta:
model = Book
fields = "name","languages", "about","image","file"
This is my view.So when I render to my update view template I get the empty form for languages and files but other are populated.
#login_required
def post_update(request,pk):
update = get_object_or_404(Book,pk=pk)
form = CreateBooksForm(request.POST or None ,request.FILES or None,instance=update)
if request.method == 'POST':
if form.is_valid():
post = form.save(commit=False)
languages = form.cleaned_data['languages']
post.save() # must be save before adding m2m
tag_list=[Language.objects.get_or_create(name=tag)[0] for tag in post.languages.lower().split()]
for tag in tag_list:
a = post.language.add(tag)
post.language.set = a
post.save()
messages.success(request,'Updated successfully!')
update_book.delay(post.pk)
context ={
'form':form
}
return render(request,'books/update.html',context)
my template.So this is simple django crispy template I have used.
<form method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
<img class="rounded-circle" src="/media/{{form.image.value}}" height="100px" width="150px">
{{ form|crispy }}
<button type="submit" class="btn btn-dark">Update Books</button>
</form>
You'll have to render each field manually to get the prepopulated field.
for example:
{% for field in form %}
{% if field.languages %}
<input type="name" id={{ field.languages.id_for_label }} value={{ field.languages.value }}/>
{% endif %}
{% endfor %}
for more details refer docs
so i'm working on little django application where users can view and modify there profile ,but i didn't know how to provide a button under the profile picture that allows the user to choose a new one and when he chooses it redirect him to the same page with the new profile picture ,any help or ideas will be usefull , tnks !!
here's what i tried :
forms.py
class picture_form(forms.ModelForm):
class Meta:
model=Profile
fields=('image',)
views.py
def profile(request):
if request.method == 'POST':
form = picture_form(request.POST, request.FILES)
if form.is_valid():
profile = Profile.objects.get(user=request.user)
profile.image = form.cleaned_data['image']
profile.save()
return redirect(reverse('profile'))
else:
for usr in User.objects.all():
if request.user.get_full_name() == usr.get_full_name():
prf = Profile.objects.filter(user=usr)
form = picture_form()
return render(request, 'store/profile.html', {'profile': prf, 'form': form})
template
{% if prf.image %}
<div class="profile-img">
<img src="{{ prf.image.url }}" id="prf_img" alt=""/>
</div>
{% else %}
<div class="profile-img">
<img src="{% static 'img/empty-profile-picture.png' %}" id="prf_img" alt=""/>
</div>
{% endif %}
<!--<a href="{% url 'upload_picture' %}"> <div class="file btn btn-lg " >
Change Photo
<input type="file" name="file"/>
</div></a> -->
<form method="post" action="{% url 'profile' %}" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-outline-success" value="upload">
</form>
</div>
Django has an awesome generic editing view called UpdateView. You can do something like this:
models.py
class Profile(models.Model):
image = models.ImageField()
views.py
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic.edit import UpdateView
#method_decorator(login_required, name='dispatch')
class UpdateProfileView(UpdateView):
model = Profile
fields = ['image']
template_name_suffix = '_update_form'
success_url = ''
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
profile_update_form.html
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
</form>
urls.py
from . import views
path('<int:pk>/update/', views.UpdateProfileView.as_view(), name='profile-update')
In my models.py, I have class with LEVEL_CHOICES and Level.
First I builded my project with a textfield Level and it worked. Then I decided to change my Level in order to give users only certain choices. Therefore I edited my models.py and I have now:
class Eleve(models.Model):
FIRST = 'FIRST'
SECOND = 'SECOND'
THIRD = 'THIRD'
LEVEL_CHOICES = (
('FIRST', 'School'),
('SECOND', 'HighSchool'),
('THIRD', 'University'),
)
Level = models.CharField(max_length=3, choices=LEVEL_CHOICES, default='FIRST')
I think that there is a problem in my views.py because I'am able to save class Eleve through Admin app. I'm also using a decorator in order to have REcaptchaV2.
def Form(request):
form = ResgisterStud(request.POST)
if request.recaptcha_is_valid and form.is_valid():
form.save(commit=False)
form.save()
return render(request, 'form.html', {'form': form})
else:
return render(request, 'form.html', {'form': form})
my forms.py
class ResgisterStud(forms.ModelForm):
class Meta:
model = Eleve
My Form.html
<form action="{% url "form" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-6 form-group">
{{ form.Level|add_class:"form-control" }}
</div>
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="form-group g-recaptcha" data-sitekey="***"></div>
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endfor %}
{% endif %}
</form>
I have the following view class:
class LoginView(View):
form_class = LoginForm
template_name = 'workoutcal/login.html'
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(email = email, password = password)
if user is not None:
if user.is_active:
login(request, user)
return calendar(request)
else:
return render(request, self.template_name, {'form':form})
else:
form['custom_error_message'] = 'Invalid user'
return render(request, self.template_name, {'form':form})
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form':form})
And this template:
login.html
{% extends "workout/base.html" %}
{% block logoutwidget %}{% endblock %}
{% block content %}
<form action="/workoutcal/login/">
{% include "workoutcal/form_disp_errors.html" %}
<input type="submit" value="Log in">
</form>
{% endblock %}
form_disp_errors.html
{% csrf_token %}
{{ form.custom_error_message }}
{{ form.non_field_errors }}
{% for field in form.visible_fields %}
<div class="row">
<div class="col-xs-2">
{{ field.label_tag }}
</div>
<div class="col-xs-2">
{{ field }}
</div>
<div class="col-xs-3">
{{ field.errors }}
</div>
</div>
{% endfor %}
When I go to workoutcal/login, type in an incorrect username and password (user doesn't exist), the page goes to workoutcal/login again, but with this url:
http://localhost:8000/workoutcal/login/?csrfmiddlewaretoken=ZywQUh7gnNfaHi8FcA3be4ynLB7SpGgwdJ0UxGzUuRYp0G0Y9LQ9e24Jx8Q1OD3Y&email=myemail%40hotmail.com&password=MYPASSWORD
As you can see in the end of the link, the password is displayed. This is obviously not good. However, I can't understand why it happens. Any ideas?
You have to use HTTP method POST, for that you must set attribute method="post" to your form tag. Like that:
<form method="post" action="/workoutcal/login/" >
With method POST request will send query string (key/value pairs) in HTTP message body instead of URL.
Note: consider using PUT/PATCH to update objects and DELETE to remove for RESTful APIs (by default Django will use method POST for all these cases).
I would like to collect the content that user input, then change the database using POST method. But i just blank when i clicked post button on the website.
Here's the views.py
class PostTweet(View):
def post(self, request, username):
form = TweetForm(request.POST)
print form.is_valid()
print request.POST
print form.errors
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()
return HttpResponseRedirect('/user/'+username)
else:
form = TweetForm()
return render(request, 'profile.html', {'form':form})
class Profile(View):
"""
User Profile page reachable from /user/<username> URL
"""
def get(self, request, username):
params = {}
user = User.objects.get(username = username)
tweets = Tweet.objects.filter(user=user)
params["tweets"] = tweets
params["user"] = user
return render(request, 'profile.html', params)
forms.py
from django import forms
class TweetForm(forms.Form):
text = forms.CharField(widget=forms.Textarea, max_length=160)
country = forms.CharField(widget=forms.HiddenInput(),required=False)
profile.html
{% extends "base.html" %}
{% block content %}
<div class="row clearfix">
<div class="col-md-6 col-md-offset-3 column">
<form id="form" method="POST" action="post/">{% csrf_token %}
<div class="col-md-8 fieldWrapper">
{{ form }}
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Post</button>
</span>
</div>
</form>
</div>
<h3> </h3>
<div class="col-md-12 column">
{% for tweet in tweets %}
<div class="well">
<span>{{ tweet.text}}</span>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
Here's the urls.py
from django.conf.urls import include, url, patterns
from django.contrib import admin
from tweets.views import Index, Profile, PostTweet, HashTagCloud
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()),
url(r'^hashTag/(\w+)/$', HashTagCloud.as_view()),
)
Anyone just give me a hint would be appreciated :-)
Adding {{form}} only should not render the field. form is an object with fields as properties. In your html try substituting {{form}} with {{form.text}}
Also you can try passing the object "form" as follows:
return render(request, 'profile.html', form = form)