I am writing a very basic web page in Python which has a text box where a user can type in a username, then hit the Ok button which submits a form using a GET request. The GET passes the username as an argument and searches the auth_user table in the database.
My problem is I am not able to pass the username argument, please help if you can Django 2.0 url patterns
urls.py
app_name = 'just_gains'
urlpatterns = [
path('lifecoaching', views.LifeCoach, name='life_coaching'),
path('lifecoaching/resultslifecoaching/<str:user_name>', views.LifeCoachSearchResults, name='results_life_coaching'),
]
forms.py
class LifeCoachSearch(forms.Form):
user_name = forms.CharField(label='Username', max_length=100, required = False)
views.py
def LifeCoach(request):
if request == 'GET':
form = LifeCoachSearch(request.GET)
if form.is_valid:
user_name = form.cleaned_data['user_name']
LifeCoachSearchResults(request,user_name)
else:
form = LifeCoachSearch()
return render(request, 'just_gains/life_coaching.html', {'form': form})
def LifeCoachSearchResults(request, user_name):
testUser = User.objects.filter(username__startswith=user_name)
context = {'TestUser': testUser}
return render(request, 'just_gains/results_life_coaching.html', context)
HTML (lifecoaching)
<form action="{% url 'just_gains:results_life_coaching' %}" method="GET" >
{% csrf_token %}
{{ form }}
<input type="submit" value="OK">
</form>
HTML (resultslifecoaching)
<ul>
<li><a>print usernames that match the argument</a></li>
</ul>
Forgive me for the short response as I am on mobile. Try passing your username as a string in the path using <str:user_name>
Usually I think the form should submit via POST rather than GET, and the value of the submitted username would then be available in the dictionary request.POST['username']. GET should be used to get forms from the server; POST posts information back to the server. POST ensures that the browser bundles everything in the form and sends it complete, but GET tries to encode it in the URL and makes no guarantees.
Using forms, its helpful to have the View divide so that GET requests pull up blank or prepopulated forms (the empty search box) and POST requests are processed and redirected to the parameterized results screen you have.
You would then create a httpRedirect to re-assign the request to your URL with a parameter. I think this link, example 2 is the right way to go.
https://docs.djangoproject.com/en/2.0/topics/http/shortcuts/#redirect
So your function would look like:
def LifeCoach(request):
if request.method = 'GET':
return render(request, 'just_gains/life_coaching.html', context)
elif request.method = 'POST':
# I have skipped form validation here for brevity
return redirect('results_life_coaching',request.POST['username'])
It's possible that having a field called username may clash with or confuse you later when using request.USER['username']. Don't forget to change your form html! All the best!
[Edit 1] My code was wrong; GET should call the lifecoaching form, POST should redirect to the results_life_coaching page.
[Edit 2] My suggestions for your templates:
HTML (lifecoaching.html)
<form action="{% url 'just_gains:life_coaching' %}" method="POST" >
{% csrf_token %}
{{ form }}
<input type="submit" value="OK">
</form>
HTML (resultslifecoaching.html)
<ul>
{% for item in username_list %}
<li>{{item.user_name}} - {{item.achievement}} </li>
{% endfor %}
</ul>
Related
I am trying to delete an object from database using simple html button. Also, trying to implement "are you sure" message? BUt I am getting this error everytime and I am not able to crack.
This is my view function.
def customerdel(request,pk):
objs = Customer.objects.filter(id=pk)
if request.method == 'POST':
objs.delete()
# messages.success(request, 'Successfully deleted')
return render(request,'records.html')
else:
content ={
'items':Customer.objects.all
}
return render(request,'delete.html', content)
This is record.html page
<h1>Record's page</h1>
{% for abc in Customerdata %}
{{abc.name}}
{{abc.pk}}
<form >
<button class="btn btn-danger btn-sm">
Delete</button>
</form>
{% endfor %}
This is delete.html page
<h1>Welcome to Delete page</h1>
<p>Are you sure want to del {{items.name}} ??</p>
<form action="{% url 'customerdel' items.pk %}" method="post">
{% csrf_token %}
Cancel
<input name="confirm" type="submit" >
</form>
This is my URL.
path('dashboard/records/customerdel/<int:pk>', views.customerdel, name='customerdel'),
You are doing wrong while template rendering as you are not sending any data to the template.But inside the record.html you are trying to iterate over CustomerData which is not defined.So send it to the template or another way is to simply redirect to the route which is made for rendering record.html.
Here is the full code which you should apply in your django project to make it work.
from django.http import HttpresponseRedirect
from django.urls import reverse #these two lines are required for redirecting to a previous route(url)
As you must have set a url which takes to the records function something like this;
path('records', views.records, name='records')
If you haven't added the name, add it.
Then in views.py, in customerdel function;
if request.method == 'POST':
#write your code which you already wrote and instead of return render(...) write this;
return HttpResponseRedirect(reverse('records')) #where records is the name of the url which takes us to the records page.
What I really want to do is , if a user click on "ADD more" button then a same form repeat itself and the values should store in database, if he/she doesn't click of that button then only the values from first form should be stored.
I am not able to get this, I just created a form , and a table in database for those details but can't loop though the form neither in data.
please help.
This is the form and the button:
This is the model.py code:
from django.db import models
class experience(models.Model):
company_name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
startdate = models.Datefield(default = 01-01-2020)
lastdate = models.DateField(default = 01-01-2020)
profile = models.CharField(max_length=100)
description = models.TextField(max_length = 250)
This is the views.py code:
from django.shortcuts import render, redirect
import requests
from django.contrib.auth.models import User, auth
# Create your views here.
def profile(request):
return render(request, 'profile.html')
Unfortunately, there's no built-in way (as far as I know) in Django to do that without Javascript, but here's an approach:
HTML:
<div class="container" id="experiencesContainer">
<form method='POST' name='experienceForm'>
{{form.as_p}}
</form>
<form method='POST' name='experienceForm'>
{{form.as_p}}
</form>
<button type="button" id="addMoreButton">Add more</button>
<button type="submit">Save Changes</button>
</div>
Django POST method:
# Get a list of submitted forms
experiences = request.POST.getlist('experienceForm')
for experience in experiences:
# this is how you loop throuh every form
experience.get('company_name)
Your javascript something like:
// clonning his childs as well
let cloneForm = document.querySelector('form[name=experienceForm]').cloneNode(true);
document.querySelector('div#experiencesContainer').appendChild(cloneForm);
// see this https://www.w3schools.com/jsref/met_node_clonenode.asp
Of course this code is not tested but I've done this in several projects before, hope it works!
A simple way would be to request the same view from the "Add", just make sure your form view saves the data when request method is POST.
<form action="{% url 'your-form-url' %}" method="GET">
{% csrf_token %}
<input type="submit" value="Add">
</form>
one other way to repeat forms would be using formsets. Formsets allow you to repeat the same form 'extra' times. Check out the documentation for more about this.
def repeat_form(request):
ExpFormSet = formset_factory(ExperienceForm, extra=3)
#extra defines the no. of forms you want to display
if request.method == 'POST':
formset = ExpFormSet(request.POST, request.FILES)
if formset.is_valid():
# do something with the formset.cleaned_data
#loop through each form in the formser
for form in formset.cleaned_data:
obj = form.save()
else:
formset = ExpFormSet()
return render(request, 'exp_form.html', {'formset': formset})
The corresponding template should be:-
<form method="post">
{{ formset.management_form }}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
</form>
Make sure you add form.management_form. Using the combination of the above might solve your problem of taking and saving several inputs.
I'm learning django, in this moment I'm trying to implement web forms, actually some of them works fine with the data base model but I'm trying to make a new one without use the models. The problem is that django show me the token and not the value typed in the form.
I hope you can help me, to understand more about it.
URLS:
url(r'^test', views.test),
VIEWS:
def test(request):
if request.method == "POST":
return HttpResponse(request.POST)
return render(request, 'datos.html')
DATOS HTML:
<form action="/test" method="post" name="myForm"> {% csrf_token %}
<input type="text">
<input type="submit">
</form>
When I run this django show me:
csrfmiddlewaretoken
Can any one help me please?
To protect from Cross-Site_Request_Forgery attack, for each post request we need to send a csrf token, from the form, which is missing in your form, you can get rid of this error by modifying your form as follows.
<form action="/test" method="POST" name="myForm">
{% csrf_token %}
<input type="text">
<input type="submit">
</form>
and You need to get the data from your views,
def test(request):
if request.method == "POST":
# Getting the value of text field from the form
# If the value is empty set the default value to None
text = request.POST.get('text', None)
# Do not return the POST request
# Return the value you get from the form
return HttpResponse(text)
# This code is not going to execute
# Return is already encountered above in our code
return render(request, 'datos.html')
# To send data to form do,
# return render(request, 'datos.html', {'my_data': text})
I have a base template which contains header, footer and a block "content" which then I override in different CBVs.
There is little "user-space" divinside a header where I want to keep user's info in case he is logged in and a login form if he is a guest.
Right now the only way that comes in mind is to create a django app and use it as a tag. But I think there is a better solution. Because as far as I know tags can slow down django project in future.
Also I think that maybe I would like to manipulate this div from a view which renders a child template. For example I calculate and display some value on a page but also I want to display it in a "user-space" div as well. I think this can be achieved by pushing data to the user's session and then using this while rendering "user-space" div from another code.
Assuming you have django.contrib.auth.user in your INSTALLED_APPS, you can access the user's login status using user.is_authenticated():
{% if user.is_authenticated %}
<div>Welcome back, {{ user.username }} | <a href='/logout/'>Logout</a></div>
{% else %}
<div>
<form action='/login/' method='POST'>
{{ csrf_token }}
{{ login_form }}
<input type='submit'>
</form>
</div>
{% endif %}
Edit:
In response to your comment:
Let's suppose client does a POST request by which we calculate some number - total price. And I need to display it in that div.
As documented
Define your view:
from django.shortcuts import render
from .forms import MyForm
def simple_view(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = MyForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
result = form.cleaned_data['some_input'] * 50
return render(request, 'my_template.html', {'result': result})
# if a GET (or any other method) we'll create a blank form
else:
form = MyForm()
return render(request, 'my_other_template.html', {'form': form})
Display result in your template:
<!-- my_template.html -->
<div>{{ result }}</div>
Maybe you need to be more specific with your question, this is what I think you are looking for though. You should put logic like you are describing into a view, not a template.
I am lost here. I am quite new to django and maybe this is a newbie question.
I have a very simple list view , which shows the records in the database and a create view to add these objects :
#login_required
def list_view(request):
objects = Foo.objects.all()
ctx = {'objects': objects}
return render_to_response('main/foos.html', ctx,
context_instance=RequestContext(request))
#login_required
def create_view(request):
if request.method == 'POST':
form = FooForm(request.POST)
if form.is_valid():
form.save()
return redirect('/foos/')
else:
form = FooForm()
ctx = {'form': form}
return render_to_response('main/foo_form.html', ctx,
context_instance=RequestContext(request))
The foo_form.html template looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Club</title>
</head>
<body>
<form action="." method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Confirm/>
</form>
</body>
</html>
Url settings:
urlpatterns = patterns('',
url(r'^foos/$', 'list_view'),
url(r'^foos/new$', 'create_view'),
)
When I type the url "localhost:8000/foos/new", the create view gets the GET request as expected. The problem is, upon submitting the form, I am redirected to the list (using a debugger I found out the request is getting to the list_view), even when form action is set to "."
What am I doing wrong? The create_view view should receive the POST request .
Any help is appreciated! Again, I am sorry if this is a newbie question
You haven't finished the regex string in the second url
url(r'^foos/new$', 'create_view')
so "." will use the current url to POST the form. Django takes the url '/foos/new' and matches it against the regex. It matches the first regex, as it finds a match for 'foos', so goes to the 'list_view'. Just finish your regex correctly and it will work.
url(r'^foos/new/$', 'create_view')
Leave the form action as "" to post to the same url rather than having a .
So in this case
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Confirm/>
</form>