The form is always sending a Get request instead of a Post which has been explicitly added using method = "POST". So, not able to persist the data to db. I have just started with Django so, any help will be appreciated.
Below are the code snippets:
create_order.html
<form method="POST" action="{% url 'home' %}">
{% csrf_token %}
{{form}}
<input class="btn btn-primary btn-sm" type="submit" name="Submit">
</form>
urls.py
urlpatterns = [
path('', views.dashboard, name='home'),
path('products/', views.product, name='products'),
path('customer/<str:cust_id>/', views.customer, name='customer'),
path('create_order/', views.create_order, name='create_order'),
]
views.py
def create_order(request):
form = OrderForm()
if request.method == 'POST':
print("In Post", request.method)
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
print("In else", request.method)
print(form.is_valid())
if form.is_valid():
form.save()
return redirect('/')
context = {'form' : form}
return render(request, 'accounts/create_order.html', context)
terminal output
In else GET False
You are making a POST request to the wrong view. It should be the create_order view, so:
<form method="POST" action="{% url 'create_order' %}">
{% csrf_token %}
{{ form }}
<input class="btn btn-primary btn-sm" type="submit" name="Submit">
</form>
Note that you should not validate the form in case of a GET request, since then you only render the form. So the view logic should be:
def create_order(request):
if request.method == 'POST':
print("In Post", request.method)
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
form = OrderForm()
context = {'form' : form}
return render(request, 'accounts/create_order.html', context)
Try to add form action method in your HTML file
<form action="" method="post">{% csrf_token %}
{{ form}}
<input type="submit" value="Submit Feedback" />
</form>
</div>
Related
I have two buttons in my django site's form, the first one is supposed to only call a javscript function and the second one is supposed to submit the form.
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.title|as_crispy_field }}
<br/>
{{ form.body|as_crispy_field }}
<button class="btn mt-3" onclick="insertText('HELLO')">Insert Text</button>
<br/>
<button class="btn btn-success mt-3" >Submit!</button>
</form>
My 'views.py' file contains following code for this page:
class Posts(View):
def get(self, request, *args, **kwargs):
form = PostForm()
posts = Post.objects.all().order_by('-publish_date')
context = {
'form': form,
'posts': posts
}
return render(request, 'posts/view_posts.html', context)
def post(self, request, *args, **kwargs):
form = PostForm(request.POST, request.FILES)
if form.is_valid():
new_post = form.save(commit=False)
new_post.publisher = request.user
new_post.save()
form = PostForm()
return redirect('view-posts')
My problem is the 1st button that is supposed to be only calling a javascript function is also making a POST request and submitting the form.
Any solution to this problem?
You can name your button as
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.title|as_crispy_field }}
<br/>
{{ form.body|as_crispy_field }}
<button class="btn mt-3" onclick="insertText('HELLO')" name="not_save_button">Insert Text</button>
<br/>
<button class="btn btn-success mt-3" name="save_button">Submit!</button>
</form>
And in post method of your view:
def post(self, request, *args, **kwargs):
form = PostForm(request.POST, request.FILES)
if form.is_valid() and 'save_button' in request.POST:
new_post = form.save(commit=False)
new_post.publisher = request.user
new_post.save()
form = PostForm()
return redirect('view-posts')
I am using the UserCreationForm for user registration in my Django web app. When the user fills in the detail (username, password, confirm_password) and submits, then if the form fails validation (maybe because username already exists or password don't match or password is too short) then the user is redirected back to the register page.
Now my problem is that when he is redirected back to the register page, the form is blank again, i.e. he has to start all over again, which is not a good user experience because his form might fail one or more times.
I want that if the form fails validation and when he is redirected to the registration form, he should see his previously filled in details so that he can just correct the field which is causing the error and move on. Is there any way the data can be retained?
Here is my code of the register function in views.py:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST or None)
if form.is_valid():
# some code
return redirect('login')
else:
messages.error(request, form.errors)
return HttpResponseRedirect(reverse("register"))
else:
return render(request, 'accounts/register.html')
my register.html:
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
<input name="username" type="text" class="..." style="...">
<input name="password1" type="password" class="..." style="...">
<input name="password2" type="password" class="..." style="...">
<button type="submit">Sign up</button>
</form>
Edit:
I have not passed the form in context to the template, so that I can control the CSS of my input fields, which I am not sure how to do otherwise without creating forms.py file separately.
If it's not possible to retain details in the form, then what should I do to at least improve the present situation?
Instead of return redirect just render the response with the form object again:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST or None)
if form.is_valid():
# some code
return redirect('login')
messages.error(request, form.errors)
else:
form = UserCreationForm()
return render(request, 'accounts/register.html', {'form': form})
In the template since you want to control css use django-widget-tweaks:
{% load widget_tweaks %}
<form method="POST" action="{% url 'register' %}">
{% csrf_token %}
{% render_field form.username class="..." style="..." %}
{% render_field form.password1 class="..." style="..." %}
{% render_field form.password2 class="..." style="..." %}
<button type="submit">Sign up</button>
</form>
The load widget tweaks must be at the top of the html file like all load tags.
def register(request):
context = {}
if request.method == 'POST':
form = UserCreationForm(request.POST or None)
if form.is_valid():
# some code
return redirect('login')
else:
context['form'] = form
messages.error(request, form.errors)
context['form'] = UserCreationForm()
return render(request, 'accounts/register.html', context)
it should work
I have a for loop that lists all the testimony instances in my model. I'd like to have the button in the code below delete the related instance when clicked.
html
{% block content %}
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<button type="button" class="btn btn-danger">Delete</button>
</a>
{% endfor %}
****
{% endblock content %}
views.py
def create_testimony_view(request):
if request.method == "POST":
form = CreateTestimonyForm(request.POST)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm
context = {
"title": "Create - Testimony",
"form": form,
"testimonies": Testimony.objects.all(),
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
def update_testimony_view(request, slug):
instance = get_object_or_404(Testimony, slug=slug)
if request.method == 'POST':
form = CreateTestimonyForm(
request.POST, request.FILES, instance=instance)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm(instance=instance)
context = {
"title": "Update - Testimony",
"form": form,
"instance": instance,
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
Thanks for any help
You need to make a POST request to the server which will delete the instance.
Please have a look at Form documentation. https://docs.djangoproject.com/en/3.0/topics/forms/
You need to add simple form and view to delete testimony.
html,
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<form action="{% url 'main:delete_testimony' testimony.pk %}" method="POST">
<button type="button" class="btn btn-danger">Delete</button>
</form>
</a>
{% endfor %}
view,
def delete_testimony(request, pk):
deleted = False
try:
Testimony.objects.delete(pk=pk)
deleted = True
except Testimony.DoesNotExist:
pass
return JsonResponse({'deleted':deleted})
When I tried to register in my site, it's instantly buffering,
The server is working properly and others were coded finely.
The urls.py
urlpatterns = [
#Login Page
url(r"^login/$", login, {'template_name':'users/login.html'},
name='login'),
#Logout Page
url(r"^logout/$", views.logout_view, name="logout"),
# Registration Page
url(r"^register/$", views.register, name='register'),
]
The views.py
def register(request):
"""Register a new user."""
if request.method != "POST":
#display blank register form.
form = UserCreationForm()
else:
# process completed form.
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
# Log the user in and then redirect to home page
authenticate_user = authenticate(username=new_user.username,
password=request.POST['password1'])
login(request, authenticate_user)
return HttpResponseRedirect(reverse('learning_logs:index'))
context = {'form': form}
return render(request, 'users/register.html', context)
Double checked I am in the right views.py
The register.html is:
{% extends "learning_logs/base.html" %}
{% block content %}
<form action="{% url "users:register" %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">log in</button>
<input type="hidden" name="next" value="{% url "learning_logs:index" %}">
</form>
{% endblock content %}
Where might be the problem live?
TOday I am trying to make some kind of to-do list. I know how to add tasks(comments) and now I want to delete them with a button. I don't know how to delete exact task (comment). Code:
#views.py
def add_comment(request):
comments = Comment.objects.all()
if request.method == 'POST':
form = CommentForm(request.POST)
if "delete" in request.POST:
#HERE MAGIC HAPPENS
if form.is_valid():
save_it = form.save()
return render(request, 'task-result.html', {
'form': form, 'comments': comments,
})
else:
form = CommentForm()
return render(request, 'Task-form.html', {
'form': form,
})
#HTML
<form action="">
{% for a in comments %}
<h3>{{ a.body}}</h3>
<input type="submit" name="delete" value="delete" />
{% endfor %}
{% csrf_token %}
</form>
So how to make "magic" happen?
Addition
Now I'm facing new problems. Delete button does nothing or i get eroor: invalid literal for int() with base 10: ''. Code:
#Template:
<html>
<head>
<title>Name</title>
</head>
<body>
<h1>Tasks</h1>
<form action="" method="post">
{{ form.as_p }}
<input type="submit" value="Create task">
{% for a in comments %}
<h3>{{ a.body}}</h3>
<input type="submit" name="delete" value="delete" />
<input type="hidden" name="idcomment" id="{{comments.id}}" />
{% csrf_token %}
</form>
{% endfor %}
</body>
</html>
#Views
def add_comment(request):
comments = Comment.objects.all()
if request.method == 'POST':
form = CommentForm(request.POST)
if "delete" in request.POST:
comments_id = request.POST['idcomment']
comments_object = Comment.objects.get(id=comments_id)
comments_object.delete()
if form.is_valid():
save_it = form.save()
return render(request, 'task-form.html', {
'form': form, 'comments': comments,
})
else:
form = CommentForm()
return render(request, 'Task-form.html', {
'form': form, 'comments': comments,
})
Can you help me solve this one?
My solution will be to add a function delete in your views that will take for argument the comment number.
def del_comment(request, commentsid):
comments = Comment.objects.get(id=commentsid)
comments.delete()
and your url:
url(r'^yoururl/del/(?P<commentsid>\d+)/', del_comment),
in your template link your comment button delete to this url
yoururl/del/{{yourvalue of the comment that will give the id of the current comment}}
example in templates:
{% for a in comments %}
<h3>{{ a.body}}</h3>
Delete ME
{% endfor %}
There is another solution that may work:
if request.method == 'POST':
form = CommentForm(request.POST)
if "delete" in request.POST:
comments_id = request.POST['idcomment'] #the name of the hidden field and get the id of the comment.
comments_object = Comment.objects.get(id=comments_id)
comments_object.delete()
if form.is_valid():
save_it = form.save()
return render(request, 'task-result.html', {
'form': form, 'comments': comments,
})
the hidden field should look like this in your template:
<input type="hidden" name="idcomment" id="{{comments.id}}" /> #or value="{{comments.id}} sorry i do not have my own example on hand.