I have a contact page with a simple form.
Here is views.py:
def contact_view(request):
if request.method == 'GET':
form = ContactForm()
else:
form = ContactForm(request.POST)
if form.is_valid():
subject = form.cleaned_data['subject']
from_email = form.cleaned_data['from_email']
message = form.cleaned_data['message']
try:
send_mail(subject, message, from_email, settings.ADMIN_EMAILS)
except BadHeaderError:
return HttpResponse('Invalid header found.')
return redirect('success')
return render(request, "base/contact.html", {'form': form})
def success_view(request):
return HttpResponse('Success! Thank you for your message.')
this is contact.html:
{% block content%}
<main class="page contact-page">
<section class="portfolio-block contact">
<div class="container">
<div class="heading">
<h2>Contact me</h2>
</div>
<form method="post">
{% csrf_token %}
<div class="mb-3"><label class="form-label" for="name">Your Name</label><input class="form-control item" type="text" id="name"></div>
<div class="mb-3"><label class="form-label" for="subject">Subject</label><input class="form-control item" type="text" id="subject"></div>
<div class="mb-3"><label class="form-label" for="email">Email</label><input class="form-control item" type="email" id="email"></div>
<div class="mb-3"><label class="form-label" for="message">Message</label><textarea class="form-control item" id="message"></textarea></div>
<div class="mb-3"><button class="btn btn-primary btn-lg d-block w-100" type="submit" value="submit">Submit Form</button></div>
</form>
</div>
</section>
</main>
{% endblock %}
When I use form.as_p it works very well but when I use this template it is not working
it only shows in the terminal that a post request was made.
The html looping syntax of form is following, where we have access to specific field, field.label ,non_field_errors as well as particular field errors.
In your case you can use in this way:
contact.html
{% block content%}
<main class="page contact-page">
<section class="portfolio-block contact">
<div class="container">
<div class="heading">
<h2>Contact me</h2>
</div>
<form method="POST" novalidate>
{% csrf_token %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<div>
{{error}}
</div>
{% endfor %}
{% endif %}
{% for field in form %}
<p>{{field.label_tag}} {{field}}</p>
<br>
{% for error in field.errors %}
<span>{{error}}</span>
{% endfor %}
{% endfor %}
<input type="submit" value="Save">
</form>
</div>
</section>
</main>
{% endblock %}
You can use it as above it will work perfectly with your existing views, as you said it is working with form.as_p.
If you give only form.as_p, it will render form fields in <p> tag of html, you can see through Ctrl+U of view page source,there we cannot have more control over form.
Your question -- How can i use bootstrap's classes in django's form?
Answer - You can set through widget in your form's fileds. for example:
class MyForm(forms.Form):
name=forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
In the above way, you can set it to every field.
Related
Under views.py
def addcomments(request):
comment_text = request.POST.get('comment')
user_id = request.POST.get('user_id')
name = request.POST.get('name')
email = request.POST.get('email')
comment = Comment.objects.create(user_id=user_id, body=comment_text, name=name, email=email)
comment.save()
return HttpResponseRedirect(reverse('users:detail', args=(user_id, )))
this one, from detail.html
{% extends 'base.html' %}
{% block title %}
{{ user.user_fname }} {{ user.user_lname }}
{% endblock %}
{% block content %}
{% if error_message %}
<p class="alert alert-danger">
<strong>{{error_message}}</strong>
</p>
{% endif %}
<div class="row">
<div class="col-lg-6">
<div class="mb-5">
<h1>{{ user.user_fname }} {{ user.user_lname }}</h1>
<p class="text-muted">{{ user.user_email }}</p>
<p>Position: {{ user.user_position }}</p>
</div>
<div class="img-responsive">
<img src="/users/media/{{user.user_image}}" alt="profile_user" class="img-rounded" width="300">
<!-- ito yung hinahanap ng search engine-->
</div>
<div class="btn-group mt-5">
Delete
Edit
Back
</div>
</div>
<div class="col-lg-6">
<h2>Comment</h2>
<p class="text-muted"> Number of comment : {{ comments_count }}</p>
{% if comments_count > 0 %}
{% for comment in comments %}
{% if comment.active %}
<p><strong>{{comment.name}}</strong> : {{comment.body}}</p>
{% endif %}
{% endfor %}
{% endif %}
<hr>
<br><br><br><br><br><br>
<form action="{%url 'users:addcomments'%}" method="post">
{% csrf_token %}
<div class="form-group">
<label>Comment</label>
<textarea name="comment" id="comment" cols="30" rows="5" class="form-control" required placeholder="Enter your comment here ..."></textarea>
</div>
<br>
<input type="text" name="name" id="name" value="{{ user.user_lname }}">
<input type="text" name="lname" id="lname" value="{{ user.user_fname }}">
<input type="text" name="email" id="email" value="{{ user.user_email }}">
<br><br><br><br>
<button type="submit" class="btn btn-sm btn-primary">Add Comment</button>
</form>
</div>
</div>
{% endblock %}
this one for url.py
path('addcomments', views.addcomments, name='addcomments'),
I am having the error message,
IntegrityError at /users/addcomments
(1048, "Column 'user_id' cannot be null")
During handling of the above exception ((1048, "Column 'user_id' cannot be null")), another exception occurred:
from 404
users\views.py, line 146, in addcomments
comment = Comment.objects.create(user_id=users_id, body=comment_text, name=name, email=email) …
Local vars
Variable Value
comment_text
'wwerwr'
email
'HeavyRain#gmail.com'
name
'Heavy'
request
<WSGIRequest: POST '/users/addcomments'>
user_id
None
the heavyrain details, ignore it, was trying stuffs
this one for detail detail is working fine properly, detail is on left side of the page, while addcomments is on the right side of the same page
#login_required(login_url='/users/login')
def detail(request, profile_id):
try:
user = User.objects.get(pk=profile_id)
comments = Comment.objects.filter(user_id=profile_id)
comments_count = Comment.objects.filter(user_id=profile_id).count()
except User.DoesNotExist:
raise Http404("Profile does not exist")
return render(request, 'UI/detail.html', {'user': user, 'comments': comments, 'comments_count': comments_count})
You don't have an user_id field in your html form that's why it becomes None or null and since you don't allow your user_id to be none (don't allow it to be none) django fails to create it. I suggest you get rid of the user_id in the creation and search for a user with that exact unique username that posted the form with
user = request.user
comment = Comment.objects.create(user=user, body=comment_text, name=name, email=email)
I'm sorry but use a model form. It's the MOST appropriate solution. It will manage rendering your form in html and ensuring data is clean and validated.
from django import forms
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = [...]
Please see further information in the documentation.
https://docs.djangoproject.com/en/4.1/topics/forms/modelforms/
I made a template tag and when I am using that in my template I get this error:
'str' object has no attribute 'as_widget'
This is the code of my template tag:
from django import template
register = template.Library()
#register.filter
def field_type(bound_field):
return bound_field.field.widget.__class__.__name__
#register.filter
def input_class(bound_field):
css_class = ''
if bound_field.form.is_bound:
if bound_field.errors:
css_class = 'is-invalid'
elif field_type(bound_field) != 'PasswordInput':
css_class = 'is-valid'
return 'form-control {}'.format(css_class)
and my template is here:
{% extends 'board/account.html' %}
{% load widget_tweaks %}
{% load form_tags %}
{% block title %}Sign up{% endblock title %}
{% block content %}
<div class="accountform">
<form method="POST">
<h4 class="display-6 text-white p-3">Create your account</h4>
{% csrf_token %}
<div class="alert alert-danger p-0" style="border:none;">
{% for field in form.visible_fields %}
{% for error in field.errors %}
<span class="err">{{ error }}</span><br>
{% endfor %}
{% endfor %}
</div>
<div class="form-group">
<label for="id_username">Username</label>
{% render_field form.username|input_class class='form-control' placeholder='John Doe' %}
</div>
<div class="form-group">
<label for="id_email">Email</label>
{% render_field form.email|input_class class='form-control' placeholder='johndoe#email.com' %}
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="id_password1">Password</label>
{% render_field form.password1|input_class class='form-control' placeholder='****' %}
</div>
<div class="form-group col-md-6">
<label for="id_password2">Confirm Password</label>
{% render_field form.password2|input_class class='form-control' placeholder='****' %}
</div>
</div>
<input type="submit" value="Sign up" class="btn btn-primary btn-block">
<p class="display-6 bg-signup p-3">Have an account Sign In</p>
</form>
</div>
</div>
{% endblock content %}
I saw similar question and approved answer in SO which basically says that the solution for this issue is to add form in context, well that is already added, here is views
def signup_view(request):
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect('board:home')
form = UserRegistrationForm(request.POST)
return render(request, 'accounts/signup.html', {'form': form})
Please help me solve this issue. Thank you for your help.
There doesn't seem to be any reason for either of these template tags. django-widget-tweaks already has the ability to add a custom error class with render_field, and you already know when you're rendering the password field so you can add that class when you need to.
(Also, django-widget-tweaks provides the field_type filter already).
So:
{% with WIDGET_ERROR_CLASS='my_error' %}
<div class="form-group">
<label for="id_username">Username</label>
{% render_field form.username class+='form-control' placeholder='John Doe' %}
</div>
<div class="form-group">
<label for="id_email">Email</label>
{% render_field form.email class+='form-control' placeholder='johndoe#email.com' %}
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="id_password1">Password</label>
{% render_field form.password1| class+='form-control' placeholder='****' %}
</div>
...
{% endwith %}
You are doing it wrong way you have to add calss in class attribute not render class name as field. Do it like this.
{% render_field form.username class=form.username|input_class placeholder='John Doe' %}
Im tries to open in Django the user edit form in Bootstrap modal. But the form is empty, only the save button is shown. But I don't understand how I can make the connection. If I call the edit page directly, then I can edit the user
127.0.0.1:8000/account/edit/
index.html, includes the referral to the form
{% extends 'base.html' %}
{% block head %}
{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-6">
<div class="panel panel-default">
<div class="panel-body">
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form action="{% url 'account:edit_profile' %}">
<input type="submit" value="Edit" />
</form>
<form action="{% url 'account:change_password' %}">
<input type="submit" value="Change Login" />
</form>
<br>
Open Modal
<br>
<div class="control-label col-sm-2">
First name:
</div>
<div class="col-sm-2">
{{ user.first_name }}
</div><br>
<div class="control-label col-sm-2">
Last name:
</div>
<div class="col-sm-2">
{{ user.last_name }}
</div><br>
<div class="control-label col-sm-2">
Email:
</div>
<div class="col-sm-2">
{{ user.email }}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="edit-profile-modal" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" align="center">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</div>
<div id="div-forms">
{% include "account/edit_profile.html" with form=form %}
</div>
</div>
</div>
</div>
{% endblock %}
edit_profile.html
{% block head %}
{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<h3>Profile</h3>
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
<button type="submit">Save</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
views.py
def edit_profile(request):
if request.method == 'POST':
user_form = EditUserForm(request.POST, instance=request.user)
if all([user_form.is_valid(), profile_form.is_valid()]):
user_form.save()
return render(request, 'account/index.html')
else:
user_form = EditUserForm(instance=request.user)
args = {'user_form': user_form}
return render(request, 'account/edit_profile.html', args)
urls.py
urlpatterns = [
...
url(r'^edit/$', views.edit_profile, name='edit_profile'),
...
]
forms.py
class EditUserForm(forms.ModelForm):
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name'
)
Im using:
Python 3.6.3
Django 2.0.7
Windows 8.1
Bootstrap 3.3.6
JQuery 1.12.0
I think that variable form doesn't exist and you use in template just user_form not form variable
{% include "account/edit_profile.html" with form=form %}
Try use it:
{% include "account/edit_profile.html" with user_form=user_form %}
Maybe you could try the code I wrote and you can find it at django-bootstrap-modal-forms. You will be able to bind your form to the modal and all of the validation stuff will work out of the box.
You will create a trigger element opening the modal
Your selected form will be appended to the opened modal
On submit the form will be POSTed via AJAX request to form's URL
Unsuccessful POST request will return errors, which will be shown under form fields in modal
Successful POST request will redirects to selected success URL
I have searched some posts about this issue but still not find solution. After clicking the "submit", the page could redirect to another page. But the sql database doesn't show the submitted information.
Thanks in advance for your suggestion.
views.py
#csrf_exempt
def input(request):
if request.method == 'POST':
form = InputForm(request.POST or None, request.FILES or None)
if form.is_valid():
company = form.cleaned_data['company']
region = form.cleaned_data['region']
uom= form.cleaned_data['uom']
start_date= form.cleaned_data['start_date']
end_date= form.cleaned_data['end_date']
add_input=Input.objects.create(company=company,region=region,uom=uom,start_date=start_date,end_date=end_date)
add_input.save()
return redirect('resut')
else:
print(form.errors)
else:
form = InputForm(initial={'company':'coco','uom':'M$'},instance=Input)
return render_to_response('inputform.html',{'form': form})
models.py
class Input(models.Model):
company=models.CharField(max_length=100)
region=models.CharField(max_length=100)
uom=models.CharField(max_length=100)
start_date=models.DateField(auto_now=False, auto_now_add=False)
end_date=models.DateField(auto_now=False, auto_now_add=False)
forms.py
class InputForm(forms.ModelForm):
company=forms.CharField(widget=forms.TextInput, label="Company",error_messages={'required': 'Please enter your name'},required=True)
regionlist = forms.ModelChoiceField(queryset=Dupont.objects.values('region').distinct())
uom=forms.CharField(required=True)
start_date=forms.DateField(widget=DateInput(),required=True)
end_date = forms.DateField(widget=DateInput(),required=True)
error_css_class='error'
required_css_class = 'required'
class Meta:
model = Input
fields = ('company', 'region','uom','start_date','end_date')
widgets = {
'start_date': forms.DateInput(attrs={'class':'datepicker'}),
'end_date': forms.DateInput(attrs={'class':'datepicker'}),
}
html snippet
<form action="{% url 'result' %}" method="post">{% csrf_token %}
<!--company-->
<div class="field">
<p>Company:<input type="text" name="company" value="{{company}}"/>
</div>
<!--region-->
<div class="field" >
<label> Select the Region:
{{ form.regionlist }}
{% for region in form.regionlist.choices %}
<option value="{{ val }}" {% ifequal data.val val %}selected {% endifequal %}></option>
{% endfor %}
</label>
</div>
<!--uome-->
<div class="field">
<p>Unit of Measure:<input type="text" name="uom" value="{{uom}}"/>
</div>
<!--start date-->
<label for="startDate">Start Month:</label>
<input name="start_date" id="startDate" class="date-picker"/>
<!--END date-->
<label for="endDate">End Month:</label>
<input name="end_date" id="endDate" class="date-picker" />
<!--submit-->
<div class="fieldWrapper">
<p><input type="submit" value="Submit" /></p></div>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
</form>
No, the action point to another view, instead of input view. I don't paste that view because the issue now is this form's data doesn't saved successfully.
Well then thats your problem, when you submit a form it goes to the specified action. If the snippet is the inputform.html as I suspect it is then you just need to delete the action from your form.
<form method="post">
I am currently learning python and am trying to write an app. I have the basics done. I followed a tutorial which was helpful but have gotten stuck. My understanding is 100% up to scratch yet so any help and reasoning behind it would be great.
I am getting a Method Not Allowed Error when trying to submit a form. I will post the code below and hopefully someone can help.
new_action.py
{% extends "base.html" %}
{% block content %}
<h2>New Action Request</h2>
{% include 'flash.html' %}
<div class="well">
<form class="form-horizontal" action="" method="post" name="post">
{{ form.hidden_tag() }}
<div class="control-group{% if form.errors %} error{% endif %}">
<label class="pull-right" for="post">Date: {{
datetime.date(datetime.utcnow()) }}</label>
<div class="controls">
{{form.timestamp}}
</div>
<label class="control-label" for="post">Raised By:</label>
<div class="controls">
{{ form.raised_by }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post">Source:</label>
<div class="controls">
{{ form.source }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post">Category:</label>
<div id="radios1" class="controls" data-toggle="buttons-radio">
<button type="button" class="btn active" name="health_safety" value="health_safety">Health &
Safety</button>
<button type="button" class="btn" name="quality" value="quality">Quality</button>
<input type="hidden" name="category" value={{request.form['category']}} />
</div><br/>
<br/>
<label class="control-label" for="post">Sub-Category:</label>
<div class="controls">
{{ form.sub_category }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post" width="80%" >Description:</label>
<div class="controls" >
{{ form.issue }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
<br/>
<label class="control-label" for="post">Immediate Action:</label>
<div class="controls">
{{ form.immediate_action }}
{% for error in form.errors.post %}
<span class="help-inline">[{{ error }}]</span><br>
{% endfor %}
</div>
</div>
<div class="control-group">
<div class="controls">
<input class="btn btn-primary" type="submit" value="Submit Action Request">
</div>
</div>
</form>
</div>
{% endblock %}
Views.py
#app.route('/new_action', methods=['GET', 'SET'])
#login_required
def new_action():
form = ActionRequestForm()
if request.method == 'POST':
return redirect(url_for('index'))
#actionrequest = ActionRequest(id = form.id.data, category = form.category.data)
'''post = Post(body=form.post.data, timestamp=datetime.utcnow(),
author=g.user)
db.session.add(post)
db.session.commit()
flash('Your post is now live!')'''
return render_template('new_action.html',
user = user,
form = form,
datetime = datetime
)
Your form is trying to POST data to the server. This is a HTTP POST request. You define GET and SET methods in your view. You need to use POST there.
#app.route('/new_action', methods=['GET', 'POST']) # Changed SET to POST here
#login_required
def new_action():
# ... what ever...
You should go through this RFC for HTTP. There is no SET-method.
#app.route('/new_action', methods=['GET', 'SET'])
This line of code is only allowing "GET" and "SET" methods, while you are trying to "POST" to that route.