submit multiple forms in django using custom html form - python

I have custom forms in the page suprated across the page
here is my first form
<form name="profile_image" class="edit-phto" method="POST" enctype="multipart/form-data">
<i class="fa fa-camera-retro"></i>
<label class="fileContainer">
Edit Display Photo
<input name="profile_image" value="" type="file" />
</label>
</form>
for profile picture
and i have another form for cover picture
<form name="cover_image" class="edit-phto" enctype="multipart/form-data">
<i class="fa fa-camera-retro"></i>
<label class="fileContainer">
Edit Cover Photo
<input name="cover_image" type="file" />
</label>
</form>
and another form for data :)
<form method="post" id="infoform" enctype="multipart/form-data">
{% csrf_token %}
.
.
.
.
<div class="submit-btns">
<button type="button" class="mtr-btn"><span>Cancel</span></button>
<button type="submit" class="mtr-btn" name="update"><span> Update</span></button>
</div>
and i have a form for search
<div class="searched">
<form method="post" class="form-search">
<input type="text" placeholder="Search Friend">
<button data-ripple><i class="ti-search"></i></button>
</form>
</div>
i just want to submit the 2 images forms and info forms when i click update button
is there a way to do sachthing in django without using form.as_p and stuff like that

Yes you can, you can just pass request.POST to each of your forms in the view and process each one as normal. However, you should be aware of conflicting names - the best way of managing this is to use form prefixes so that Django knows which bit of data relates to which form:
https://docs.djangoproject.com/en/4.0/ref/forms/api/#prefixes-for-forms

Related

Django UserCreationForm and Bootstrap Forms Layouts

I am trying to extend the UserCreationForm using a Bootstrap layout style for the field username. After the input tag in the registration form, I would like to add a div element like an example that I have readapted from the Bootstrap page: i.e. suggesting the user to enter the same username as the company domain.
Let's focus to the bare minimum. The form readapted from Bootstrap is:
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
<div class="col-auto">
<div class="input-group">
<input type="text" name="username" class="form-control" placeholder="your.username" id="id_username">
<div class="input-group-text">#company.domain.com</div>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
Which produces the following:
For the moment, I am using only {{form.as_p}} in my html template file:
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
{{form.as_p}}
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
And I don't know how to add the <div class="input-group-text">#company.domain.com</div> part embedded in a <div class="input-group">...</div> block.
My actual forms.py is a bit more complex, but readapted for this minimum example it contains the widget attributes as follows:
class SignupForm(UserCreationForm):
username = forms.CharField(label="",
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'your.username'}))
class Meta:
model = User
fields = (
'username',
)
Without additional libraries, is there a way to extend the widget attributes? Is it even possible to use {{form.as_p}} as I am currently doing or should I use another method?
If you want to use only {{ form.as_p }} with bootstrap then you need to install django-bootstrap.
Install it using pip:
pip install django-bootstrap4
After installation, add it in INSTALLED_APPS in settings.py file.
INSTALLED_APPS = [
'bootstrap4',
]
And in templates, you need to load it.
{% load bootstrap4 %}
{% bootstrap_messages %}
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
{% csrf_token %}
{% bootstrap_form form %} # added `form` here. we don't need to use with as_p.
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
This is the way you can use bootstrap along with {{ form.as_p }}
OR
Try another way:
Simply you can use {{ form.username }} inside an input tag in template.
For Example:
<input type="text" value="{{ form.username }}">
<form class="row gy-2 gx-3 align-items-center method="POST" action="{% url 'register' %} ">
<div class="col-auto">
<div class="input-group">
<input type="text" name="username" class="form-control" placeholder="your.username" id="id_username" value="{{ form.username }}"> #Added here
<div class="input-group-text">#company.domain.com</div>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>

How to get data from form and show in dropdown in django

What I m trying to do:
Upload a CSV file(Form #1) and show header of a CSV file in the dropdown (Form #2).
and these forms are on the same page.
What I have tried:
for now I able to upload CSV file and display header in a webpage.
index.html
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="file1">Upload Files</label>
<div class="custom-file">
<input type="file" accept=".csv" id="file1" name="file" required="True" class="form-control custom-file-input">
<label class="custom-file-label" for="file1"></label>
</div>
</div>
<div class="form-group d-flex justify-content-center">
<button type="submit" class="btn text-white w-50" value="Upload">Upload</button>
</div>
</form>
views.py
def read_csv(request):
csv_file = request.FILES['file']
data = pd.read_csv(csv_file)
i = list(data.head(0))
context = {'loaded_data': i}
return render(request, "WebApp/index.html", context)
You can use AJAX request to handle this. You can check this answer, which has a sample AJAX request. In the views.py file, you can handle the request by checking request.is_ajax() and return the context you produce from CSV file via JsonResponse. At the success part of the AJAX call, you can manipulate the dropdown DOM element. There is a good tutorial here. If you are not familiar with these, feel free to ask about the parts you are confused.
So data was in a list I just have to loop through <option>:
<select class="custom-select" id="inputGroupSelect01">
{% for x in loaded_data %}
<option value="{{ x }}">
{{ x }}
</option>
{% endfor %}
</select>

Why request.method is not getting invoked?

I have a read-only textbox which preloaded value from database which upon a button click sends it's value to a method present in backend to perform DELETE query of sql. The problem is occuring when I am click on the button the method is invoked but the request.method condition is not invoked. It is directly going to the end return statement of the method.
#app.route('/home/delete_reminder/<string:id_val>',methods=['GET','POST'])
#is_logged_in
def delete_reminder(id_val):
if request.method=='POST':
desc = request.form['description']
x = desc.split(',')
cur = mysql.connection.cursor()
cur.execute('DELETE FROM set_reminder WHERE DATE=%s,SUBJECT=%s,DESCRIPTION=%s',[x[0],x[1],x[2]])
cur.execute('DELETE FROM recur WHERE RECUR_NEXT=%s',[id_val])
flash('Reminder Deleted','danger')
mysql.connection.commit()
cur.close()
return redirect(url_for('search_reminder_to_delete'))
This is my backend code.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
Delete Reminder
{% endfor %}
</form>
This is the html part.
Your button isn't a button, it's a link. You aren't submitting your form.
If you want to fo that then you need to make you form tag:
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
and switch your button to be a real button that submits the form:
<div class="button">
<button type="submit" class="btn btn-warning">Send your message</button>
</div>
EDIT: Seeing that you want to have multiple possible routes for your form based on the loop.
You could try and use the formaction attribute, although it isn't going to be supported by every browser version.
<form method="POST">
{% for data in value %}
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button formaction="/home/delete_reminder/{{data.RECUR_NEXT}}" class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
{% endfor %}
However this will still result in your description field that is passed to the request having every single description from the whole form in a list or possibly just the last one as a single value (I can't quite remember the behaviour of multiple inputs with the same name), which I don't think is what you're expecting to happen.
It may just be easiest to create a separate form for each link in a loop to be honest:
{% for data in value %}
<form method="POST" action="/home/delete_reminder/{{data.RECUR_NEXT}}">
<div class="form-group">
<label>Description</label>
<input type="text" name="description" class="form-control" readonly="true" value="{{data.DATE}},{{data.SUBJECT}},{{data.DESCRIPTION}}">
</div>
<div class="button">
<button class="btn btn-warning" type="submit" class="btn btn-warning">Delete Reminder</button>
</div>
</form>
{% endfor %}

Get Form values in Python using Django framework

My question here is without using Model or forms.Form can we get form values on submit using Django request object.
Here is small example to explain problem.
HTML Code :
<form action="/login/" method="post">
{% csrf_token %}
<input type="text" id="USERNAME" class="text" value="USERNAME" >
<input type="password" id="Password" value="Password" >
<div class="submit">
<input type="submit" onclick="myFunction()" value="LOGIN">
</div>
<p>Forgot Password ?</p>
</form>
views.py Code :
def dologin(request):
print('i am in do login')
print(request.method)
print(request.POST)
for key, value in request.POST.iteritems():
print(key , value)
return render(request,'webapp/login.html')
So here my key values are empty always. I have learned and capable enough to create html forms using Model and forms:Form. But to add more style changes I need to map this forms:Form object to html defined form.
Thanks in advance.
Assign a name to each input
<form action="/login/" method="post">
{% csrf_token %}
<input type="text" id="USERNAME" class="text" name="USERNAME" value="USERNAME" >
<input type="password" id="Password" value="Password" name="Password" >
<div class="submit">
<input type="submit" onclick="myFunction()" value="LOGIN">
</div>
<p>Forgot Password ?</p>
</form>
HTML form elements always need a name attribute, otherwise the browser won't have any way of sending them to the backend. It's that attribute that is the key in the POST dict.
Note that any formatting you can do with HTML on its own you can also do with Django forms; you really should use them in most circumstances.
Please add the HTML attribute using name for every form component.

Simple django POST not working

I have a form like this:
<form action="{% url "forum.posts" forum=forum.slug thread=thread.slug %}" method="POST">
{% csrf_token %}
<div class="form-group">
<textarea class="form-control" placeholder="Začni tipkati.."></textarea>
</div>
<input type="submit" class="btn btn-success" value="Pošlji odgovor">
</form>
views.py
'''
Display all posts in a thread or create a new post in a thread.
'''
def posts(request, forum, thread):
forum = Forum.objects.get(slug=forum)
thread = Thread.objects.get(slug=thread)
if request.method == "POST":
return HttpResponse('ok')
posts = thread.posts.all()
return render(request, 'forum/posts.html', {
'forum': forum,
'thread': thread,
'posts': posts
})
urls.py (relevant part):
# List all posts in a thread / Submit a post to a forum
url(r'^(?P<forum>[-\w]+)/(?P<thread>[-\w]+)/$', 'forum.views.posts', name='forum.posts'),
HTML output:
<form action="/forum/o-spletiscu/novatemaa/" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="4PQWDsAfHyjrhUnYU5P9vVhtaY3vLPBU">
<div class="form-group">
<textarea name="post-body" class="form-control" placeholder="Začni tipkati.."></textarea>
</div>
<input type="submit" class="btn btn-success" value="Pošlji odgovor">
</form>
After I hit submit, I expect ok to be returned, instead page refreshes and nothing happens.
Normal GET requests are working though..
What am I missing?
Edit:
It's working when I use #csrf_exempt on posts method.
page refreshes and nothing happens
Problem with your action value. try to inspect it and find wither the url is correct or not.
OR
your form does not have any input with name property.
Try this:
<form action="{% url "forum.posts" forum=forum.slug thread=thread.slug %}" method="POST">
{% csrf_token %}
<div class="form-group">
<textarea class="form-control" placeholder="Začni tipkati.." name="something"></textarea>
</div>
<input type="submit" class="btn btn-success" value="Pošlji odgovor">
</form>

Categories