I have a form that is based on a ModelForm in my forms.py. I initially get the blank form as expected, however when filling out the form and hitting submit nothing happens. I am not sure where I am going wrong.
views.py
def add_customer(request):
# print(customer_form)
# print(customer_form.errors)
print(request.method)
print(request.POST)
customer_form = CustomerForm(request.POST or None)
if customer_form.is_valid() and request.method == 'POST':
form = CustomerForm(request.POST)
form.save()
return redirect('AdminPortal:customers')
print('posted')
else:
print('failing')
context = {'customer_form': customer_form,}
return render(request, 'add_customer.html', context=context)
urls.py
path("customers/", views.customers, name="customers"),
path("customers/customer/<int:id>/", views.customer, name="customer"),
path("add_customer/", views.add_customer, name="add_customer"),
forms.py
class CustomerForm(forms.ModelForm):
class Meta:
model = AppCustomerCst
fields = ('is_active_cst', 'name_cst', 'address_1_cst', 'address_2_cst', 'address_3_cst',
'city_cst', 'state_cst', 'zip_cst', 'country_cst', 'salesrep_cst', 'type_cst',
'is_allowed_flat_cst', 'iddef_cst', 'balance_notify_cst', 'receive_emails_cst',
'contact_domain_cst'
)
add_customer.py [form portion]
<form method="post" action='AdminPortal:add_customer'>
{% csrf_token %}
{{ customer_form }}
<button type="button" value="submit">Submit</button>
<button type="button" value="cancel">Cancel</button>
</form>
It looks like the form doesn't know where to post.
You need to turn it into a django url template tag. So I'd do something like this for your form;
<form method="post" action='{% url "AdminPortal:add_customer" %}'>
{% csrf_token %}
{% if form.non_field_errors %}
{{ form.non_field_errors }}
{% endif %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<button type="button" value="submit">Submit</button>
<button type="button" value="cancel">Cancel</button>
</form>
To find what's happening in your view I'd recommend simplifying the logic somewhat so that it's more inline with the docs here; https://docs.djangoproject.com/en/3.1/topics/class-based-views/intro/#handling-forms-with-class-based-views
Because you're doubling up the check for post & valid, I suspect you're never seeing the validation errors because they'd only come from that block of code. So change your view to be something like this and if you updated your template as above you should see some errors;
def add_customer(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
form.save()
return redirect('AdminPortal:customers')
else:
form = CustomerForm()
return render(request, 'add_customer.html', {'customer_form': form})
I found my error in the HTML Template.
I had:
<button type="button" value="submit">Submit</button>
<button type="button" value="cancel">Cancel</button>
Once Updated to:
<input type="submit" value="submit">Submit</input>
<input type="submit" value="cancel">Cancel</input>
The form posted properly as expected.
Related
How to make it such that if there are errors in the form, all the data I have keyed into the field remains and the error shows for me to edit what I need to edit.
Because it is very user-unfriendly if people press submit, and everything they have previously typed has to be retyped again due to an error that caused them to need to submit the form again.
just like when we post a stackoverflow question, if there are errors in our question eg time limit, whatever we have typed previously remains
Let me know if you require more code.
html
<form class="create-form" method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="form-group">
<label for="id_title">Title</label>
<input class="form-control" type="text" name="title" id="id_title" placeholder="Title" required autofocus>
</div>
<button class="submit-button btn btn-lg btn-primary btn-block" type="submit">Submit</button>
</form>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
views.py
def create_blog_view(request):
context = {}
user = request.user
if request.method == 'POST':
form = CreateBlogPostForm(request.POST or None, request.FILES or None)
if form.is_valid():
obj.save()
return redirect('HomeFeed:main')
else:
context['form'] = form
return render(request, "HomeFeed/create_blog.html", context)
You are rendering the fields manually by writing the tags. When you render using the form instance Django automatically sets the value attributes with the previous values. You can use {{ form.as_table }}, {{ form.as_p }}, {{ form.as_ul }}. You can also render fields individually using {{ form.title }} where title is the field name.
consider this model on Django:
class My_model(models.Model):
my_choices = { '1:first' 2:second'}
myfield1=CharField()
myfield2=CharField(choices=my_choices)
Then on my form:
class My_form(forms.ModelForm):
class Meta:
model = My_model
fields = ['myfield1', 'myfield2']
My views:
def get_name(request):
if request.method == 'POST':
form = My_form(request.POST)
if form.is_valid():
return HttpResponseRedirect('/')
else:
form = My_form()
return render(request, 'form/myform.html', {'form': form})
On my template:
{% extends "base.html" %}
{% block content %}
<form action="/tlevels/" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}
On my base.html, I will load this template like this:
{% extends "base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="p-3 mb-2 bg-info text-white" style="margin-left:20px; margin-bottom:20px;">Status</div>
<div class="form-row" style="margin-left:20px; margin-bottom:20px; margin-top:20px;">
<div class="form-group col-md-6 mb-0">
{{ form.myfield1|as_crispy_field }}
</div>
<div class="form-group col-md-6 mb-0">
{{ form.myfield2|as_crispy_field }}
</div>
</div>
<input type="submit" class="btn btn-primary" value="Submit" style="margin-left:20px;">
</form>
{% endblock %}
What I want, is to have 2 other different templates, with whatever difference on them, and load them depending on the choice made on the ChoiceField, I guess that one way could be on the view, by adding some kind of conditional, and load a different template (html file).
Any ideas?
It is possible to use {% include %} with a variable.
def some_view_after_post(request):
# ... lookup value of myfield2 ...
return render(request, "path/to/after_post.html", {'myfield2: myfield2})
The in the after_post.html template:
<!-- include a template based on user's choice -->
<div class="user-choice">
{% include myfield2 %}
</div>
You'll want to make sure there is no possible way the user can inject an erroneous choice. For example, make sure the value of myfield2 choice is valid before adding it to the context.
Im new with Django and Im trying to include my own form
My forms.py
class MyOwnForm(forms.ModelForm):
class Meta:
model = Album
fields = ['username']
My views.py
def testing_Form(request):
if not request.user.is_authenticated:
return render(request, 'login.html')
else:
form = MyOwnForm(request.POST or None)
if form.is_valid():
album = form.save(commit=False)
album.user = request.user
username = form.cleaned_data['username']
return render(request, 'form.html', {'form': form})
my form.html
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'form_template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
and the last one form_template.html
{% for field in form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<span class="text-danger small">{{ field.errors }}</span>
</div>
<label class="control-label col-sm-2" >{{ field.label_tag }}</label>
<div class="col-sm-10">{{ field }}</div>
</div>
{% endfor %}
When I open the Form Webpage, I get a empty entry field and the submit button. But when I click this button. The page is reloading and nothing more.
what do i have to do that i can work with the entered data?
But when I click this button. The page is reloading and nothing more.
Because of this, I'm assuming that you intend to show some information after the form is submitted. Here's a simple example that just displays an acknowledgement after the form is submitted.
{% if submitted %}
<div class="jumbotron contactainer">
<h1 class="display-4">Submitted</h1>
<hr class="my-4">
<p class="lead">{{ username }}'s album has been submitted</p>
</div>
{% else %}
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'form_template.html' %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
{% endif %}
views.py
def testing_Form(request):
submit = False
if not request.user.is_authenticated:
return render(request, 'login.html')
else:
form = MyOwnForm(request.POST or None)
if form.is_valid():
album = form.save(commit=False)
album.username = request.user
album.save()
submit = True
username = form.cleaned_data['username']
return render(request, 'form.html', {'username':username, 'submitted':submit})
else:
return render(request, 'form.html', {'form': form, 'submitted':submit})
You can do anything you wish with the username variable or add new variables, just remember to add them to the context dictionary if you wish to display them. The submit variable I've added is used in the template to determine what to show. Hope this helps :)
Not quite sure what you are exactly trying to achieve. However if you want to show the value of your previous submit on your screen for example as: Previous submitted username: <input username>, you can use the defined form in your template, including the values if there was a submit before.
{% if form.username.value %}
Previous submitted username: {{ form.username.value }}
{% endif %}
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{# ... all as it was ... #}
</form>
You can always add extra context to your template by assigning it to the context dictionary in the similar way you did with the {'form': form} as {'form': form, 'hello': "My hello string"} in your view.
In your template you could now use {{ hello }} as an variable.
Note that you are also using commit=False in your form to add more request data to the model after (user). Currently you left it in the unsaved state. To save the new form entry, you need to call album.save() after the modifications.
if form.is_valid():
album = form.save(commit=False)
album.user = request.user
album.save() # now commit
The username = form.cleaned_data['username'] has been defined, but never been used. Which with the example above is no longer required.
You can fetch the album objects when the user is authenticated and pass them to the template to work with as context like:
(bad practice style, but just to give you an idea within the scope of your code)
if request.user.is_authenticated:
return render(request, 'login.html')
else:
form = AlbumForm(request.POST or None)
if form.is_valid():
album = form.save(commit=False)
album.user = request.user
albums = Album.objects.all()
return render(request, 'formhandle/form.html', {'form': form, 'albums': albums})
Which you could show in your form template as:
{% if form.username.value %}
Previous submitted username: {{ form.username.value }}
{% endif %}
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{# ... all as it was ... #}
</form>
<ul>
{% for album in albums %}
<li>{{ album.user.username }}</li>
{% endfor %}
</ul>
I'm trying to get the users input and add to a table in the database, everything goes smoothly with no errors .. but the input is not added to DB
urls.py
path('category/add/', views.add_cat, name="add_cat"),
view.py
def add_cat(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CatForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
entry = Categories.objects.create(category_name=new_cat_name)
entry.save()
# ...
# redirect to a new URL:
return HttpResponseRedirect('/')
# if a GET (or any other method) we'll create a blank form
else:
form = CatForm()
return render(request, 'add_cat.html', {'form': form})
add_cat.html
{% extends 'base.html' %}
{% block content %}
{% load static %}
<form action="/" method="post">
{% csrf_token %}
{% for form in form %}
<h3 align="center">{{ form.label }}</h3>
<div align="center">{{ form }}</div>
<br>
<br>
{% endfor %}
<div align="center">
<input type="submit" class="btn btn-dark" style="width: 100px;"value="إضافة" />
</div>
</form>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
{% load static %}
<form action="" method="post">
{% csrf_token %}
{% for form in form %}
<h3 align="center">{{ form.label }}</h3>
<div align="center">{{ form }}</div>
<br>
<br>
{% endfor %}
<div align="center">
<input type="submit" class="btn btn-dark" style="width: 100px;"value="إضافة" />
</div>
</form>
{% endblock %}
change your form action, you were posting the data to '/' url but you need to put it in your add view
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
Django 1.3 documentation on class based views is seeming like a treasure hunt. How to write the class is clear enough... but what kind of template code matches each generic class? Would someone provide a complete example soup to nuts? Here's what I have so far:
urls.py
(r'^brand_create2$', BrandCreate.as_view()),
views.py
from django.views.generic import CreateView
#login_required
class BrandCreate(CreateView):
template_name = 'generic_form_popup.html'
context_object_name = "brand_thingie"
#queryset = models.Brand.objects.all()
success_url = '/'
generic_form_popup.html
????
In this case I'm exploring if it is worth learning the new style, given the older style still works:
urls.py
url(r'^brand_create1$', 'coat.views.brand_create'),
views.py
class formBrand(forms.ModelForm):
class Meta:
model = models.Brand
exclude = ('')
#login_required
def brand_create(request):
form = formBrand
if request.method == 'POST':
form = formBrand(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
passed = dict(
form=form,
MEDIA_URL = settings.MEDIA_URL,
STATIC_URL = settings.STATIC_URL)
return render_to_response('generic_form_popup.html',
passed, context_instance=RequestContext(request))
generic_form_popup.html
{% extends 'head-plain.html' %}
{% block title %}{% endblock %}
{% block headstuff %}{% endblock %}
{% block content %}
<form action="{{ action }}" method="post">
{% csrf_token %}{{ form.as_p }}
<input type="submit" value="Submit" /> </form>
{% endblock %}
CreateView inherits from ModelFormMixin, which in turn inherits from FormMixin and SingleObjectMixin.
SingleObjectMixin provides the object template context variable, which is probably not going to be any use in the case of CreateView:
object: The object that this view is displaying. If context_object_name is specified, that variable will also be set in the context, with the same value as object.
But FormMixin provides the form context variable:
form: The form instance that was generated for the view.
Thus, you can refer to the documentation to display a form with a template:
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Which means that the very template you posted should almost work with the class based view:
{% extends 'head-plain.html' %}
{% block title %}{% endblock %}
{% block headstuff %}{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}{{ form.as_p }}
<input type="submit" value="Submit" /> </form>
{% endblock %}
I removed {{ action }} because it is not part of the context, neither in the old-style view, neither with the class based view, so it doesn't make any sense. You should know that if action="" then the browser will submit to the current url. You can force the action to the current url with action="{{ request.path }}" or you can specify another url with the url template tag.
Suppose apply the best practice of naming url patterns, by changing:
(r'^brand_create2$', BrandCreate.as_view()),
to:
(r'^brand_create2$', BrandCreate.as_view(), name='band_create'),
Then you can use: action="{% url band_create %}".
You can also customize further:
<form action="/contact/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
<p><input type="submit" value="Send message" /></p>
</form>
Of course, the fields available in the form depend on your Model.