How insert 2 different forms on the same page in Django - django

I have to insert 2 forms in the same page:
1) Registration form
2) Login form
.
So if I use this in the views.py:
if request.method == 'POST':
form = registrationForm(request.POST)
if form.is_valid():
form.save()
return render_to_response('template.html', {
'form': form,
})
I will get error by submitting one of two forms.
How can I distinguish the 2 forms submitting in the views ?

You can also do like this,
<form method='POST'>
{{form1.as_p}}
<button type="submit" name="btnform1">Save Changes</button>
</form>
<form method='POST'>
{{form2.as_p}}
<button type="submit" name="btnform2">Save Changes</button>
</form>
CODE
if request.method=='POST' and 'btnform1' in request.POST:
do something...
if request.method=='POST' and 'btnform2' in request.POST:
do something...

You can submit two forms on the same page... but the action that each form calls (i.e. the view function that will process each form) should probably be different. That way, you won't have to try and distinguish the forms.
e.g. On your page:
<form id="login_form" action="{% url app.views.login %}" method="post">
...form fields...
</form>
<form id="registration_form" action="{% url app.views.registration %}" method="post">
...form fields...
</form>
And so, in views.py, you'll have a login() view function and a registration() view function that will handle each of those forms.

<form action="Page where u want to post the data" method="post">
<input name="edit" type="submit" value="Edit Client">
<input name="delete" type="submit" value="Delete Client">
</form>
just Give different names to the buttons.
if request.method == "POST" and 'edit' in request.POST:
/ Do /
if request.method == "POST" and 'delete' in request.POST:
/Do /

You can post both forms to same url too:
forms in template are like this:
<form method="post" action="/profile/">
{% for field in firstform %}
<div class="mb10">
<div class="fl desc">{{ field.label_tag }}<br />
<div class="fr">{{ field }}{{ field.errors }}</div>
<div class="clear"></div>
</div>
{% endfor %}
{% for field in secondform %}
<div class="mb10">
<div class="fl desc">{{ field.label_tag }}<br /><</div>
<div class="fr">{{ field }}{{ field.errors }}</div>
<div class="clear"></div>
</div>
{% endfor %}
<a class="submit fr" href="#""><img src="{{ MEDIA_URL }}img/save.png" /></a>
</form>
and just handle them like this in view:
if request.method == 'POST':
firstform = ProfileForm(request.POST, request.FILES, instance=profile)
secondform = UserForm(request.POST, instance=request.user)
and then do stuff with firstform&secondform.

You can have both forms posting to the same URL and have a hidden input with name set to login or registration and sort that out on the server

You can do the Registration and Login POST to different urls so each POST will be handled by corresponding view

Related

Get an object id from HTML in in request.POST

I have an user with list of tasks that he can add. I want to give him ability to delete those tasks, or mark as done.
The problem is that my solution is working only when user has one task, because of non-unique id's problem
Is there any way to pass the id to html so that it will be easily accesible in views? Thank you!
This is my current code
{% for task in tasks %}
<form id='is_checked' method='POST' action="{% url 'mark_as_done'%}" enctype="multipart/form-data">
{% csrf_token %}
<div class="input-group-text">
<input type="hidden" id="id_checked" value="{{task.id}}" name = "id_checked">
</div>
</form>
<form class="input-group" action="{% url 'delete_task'%}" method='POST' enctype="multipart/form-data">
{% csrf_token %}
<div class="input-group-prepend">
<div class="input-group-text">
<input onChange="document.getElementById('is_checked').submit()" type="checkbox" {% if task.is_done %}checked{% endif %}>
</div>
</div>
<h7 type="text" class="form-control">{{task}}</h7>
<input type="hidden" id="id" value="{{task.id}}" name = "id">
<button type="submit" class="input-group-append btn btn-danger">Delete</button>
</form>
{% endfor %}
And in views:
def delete_task(request):
if request.method == 'POST':
task = Task.objects.get(pk=request.POST['id'])
task.delete()
return redirect('tasks')
#login_required()
def mark_as_done(request):
if request.method == 'POST':
task = Task.objects.get(pk=request.POST['id_checked'])
task.is_done = True
task.save()
return redirect('tasks')```

How to use Two forms in Django Templates, And how to call different function when it submit the form

I am using two forms in one template. When i submit the 2nd form its calling first form only i'm little bit confusing where i did mistake anyone help me in this.
index.html
<form action="#" method="post">
{% csrf_token %}
<input type="text" name="username" id="username">
<button type="submit"> Submit</button>
</form>
<form action="#" method="post">
{% csrf_token %}
<input type="text" name="review" id="review">
<button type="submit"> Submit</button>
</form>
views.py
def profile(request):
if request.method == 'GET':
# Some operation
return render(request, 'index.html', {})
elif request.method == 'POST':
username = request.POST.get('username')
res = User(username=username)
res.save()
return redirect('/home/')
return redirect('/login/')
def feedback(request):
if request.method == 'POST':
review= request.POST.get('review')
res = Feedback(comment=review)
res.save()
return redirect('/home/')
return redirect('/home/')
urls.py
app_name = 'app'
urlpatterns = [
path('profile/', views.profile, name="profile"),
path('feedback/', views.feedback, name="feedback"),
]
I think the actions should be different to identify which form will make post request to which view:
<form action="{% url 'app:profile' %}" method="post">
{% csrf_token %}
<input type="text" name="username" id="username">
<button type="submit"> Submit</button>
</form>
<form action="{% url 'app:feedback' %}" method="post">
{% csrf_token %}
<input type="text" name="review" id="review">
<button type="submit"> Submit</button>
</form>
Add name attribute in submit.
<form action="#" method="post">
<input type="text" name="username" id="username">
<button type="submit" name="attr_name"> Submit</button>
</form>
And check the name in views.py
def profile(request):
if request.method == 'POST' and 'attr_name' in request.POST:
# Some operation

Delete object with form in django

I'm displaying a table. In every line there should be a delete button which deletes the element from the table.
My problem is, I'm not sure how to pass the id of the element to the view.
html:
{% for post in posts %}
<div>
<h3>Zuletzt ausgewählt:</h3>
<p>published: <b>{{ post.pub_date }}</b>
</p>
<p>
name: <b>{{ post.Name }}</b>
anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
essen: <b>{{ post.get_Essen_display }}</b>
<form action="" method="POST">
{% csrf_token %}
<input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
</form>
</p>
<p>
Email: <b>{{ post.Email }}</b>
</p>
</div>
{% endfor %}
views.py
if request.method == 'POST' and 'delete' in request.POST:
Eintrag.objects.filter(pk=id).delete()
return HttpResponseRedirect(request.path)
So I need to pass post.pub_date of every post to the view, how can I accomplish that?
My problem is, I'm not sure how to pass the id of the element to the view.
I can think of two ways to do this. I'll cover them both one by one.
1. Create a separate url route in your app specifically for deleting objects:
('/post/<pk>/delete/', name="delete_post"),
Then point your form's action to this url:
<form action="{% url 'delete_post' post.pk %}" method="POST">
...
Finally, modify your view function to accept the pk argument:
def my_view(request, pk):
...
2. Second method is to just create another field in your form and pass it the pk of the object:
Just create another field in your form.
<form action="" method="POST">
<input type="hidden" value="{{ post.pk }}" name="pk">
...
Then in your view just look at request.POST['pk'] to get the pk of the post.
A non-ajax way which is super easy to implement as it uses the Django generic views is this:
template.html
{% for post in posts %}
<div>
<h3>Zuletzt ausgewählt:</h3>
<p>published: <b>{{ post.pub_date }}</b>
</p>
<p>
name: <b>{{ post.Name }}</b>
anmeldung: <b>{{ post.get_Anmeldung_display }}</b>
essen: <b>{{ post.get_Essen_display }}</b>
<form action="" method="POST">
{% csrf_token %}
<input class="btn btn-default btn-danger" name="delete" type="submit" value="Löschen"/>
</form>
</p>
<p>
Email: <b>{{ post.Email }}</b>
</p>
<a href="/deleteurl/{{ post.pk }}">
Delete this!
</a>
</div>
{% endfor %}
Once the user clicks on the delete link they will be redirected to the delete view and template which will have a URL that looks like this "/deleteurl/1/".
Then your set of views, url, and template for processing the delete could look like this:
views.py
class DeleteMe(generic.DeleteView):
template_name = 'deleteconfirmation.html'
model = YourModel
success_url = '/YourRedirectUrl/'
urls.py
url(r'^deleteurl/(?P<pk>\d+)/$',
views.DeleteMe.as_view(), name='deletemeview'),
deleteconfirmation.html
<form action="" method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
Again, this is without the use of Ajax.
The views and template are taken directly from the Django Docs
Using POST is our priority, but I thought that adding another form will be redundant.
Found solution in django-allauth' email view.
Though it doesn't include confirmation step (as in docs, mentioned by #HoneyNutIchiros or in more details, or via onclick), it can be useful.
They add name (action_remove) to button and check it in the request.POST dict:
# account/email.html
<button type="submit" name="action_primary" >{% trans 'Make Primary' %}</button>
<button type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button>
<button type="submit" name="action_remove" >{% trans 'Remove' %}</button>
...
<button name="action_add" type="submit">{% trans "Add E-mail" %}</button>
# account/views.py
class EmailView(AjaxCapableProcessFormViewMixin, FormView):
...
def post(self, request, *args, **kwargs):
...
if "action_add" in request.POST:
res = super(EmailView, self).post(request, *args, **kwargs)
elif "action_remove" in request.POST:
res = self._action_remove(request)
...
return res

django multi form and file field

I am currently using several differences forms on a single view. I am able to fill my forms but when I submit one of them, it seems that my form is invalid. I displayed the request.POST (it contains all my information) and my form (it contains my information except files parts.)
Could you explain me how to correct it?
Could it be linked to my models?
(I am using bootstrap 3 through django)
my view :
def view_addfiles(request):
try:
print(request.POST)
except:
{}
if request.method == 'POST' and 'search' in request.POST:
print("recherche")
recherche=searchbar(request.POST, prefix='search')
if recherche.is_valid():
print("recherche")
else :
recherche=searchbar(prefix='search')
if request.method == 'POST' and 'film' in request.POST:
print("film")
addfilm=Addfilms(request.POST,request.FILES, prefix='film')
print(addfilm)
if addfilm.is_valid():
print("film")
return redirect(view_accueil, inscription=3)
else :
print("dfsd")
addfilm=Addfilms(prefix='film')
if request.method == 'POST' and 'serie' in request.POST:
print("serie")
addserie=Addseries(request.POST,request.FILES, prefix='serie')
if addserie.is_valid():
print("serie")
return redirect(view_accueil, inscription=3)
else :
addserie=Addseries(prefix='serie')
return render(request, 'menuAjout.html',locals())
my html :
<form action="{% url "add_files" %}" method="post">
{% csrf_token %}
{{ recherche.as_p }}
<input type="submit" id="validation" name="search"/>
</form>
<div id="films">
{% load bootstrap3 %}
{% bootstrap_css %}
<form action="{% url "add_files" %}" method="post">
{% csrf_token %}
{% bootstrap_form addfilm %}
{% buttons %}
<button type="submit" class="btn btn-primary" id="submitbutton" name="film" value="submit">
{% bootstrap_icon "star" %} Ajouter
</button>
{% endbuttons %}
</form>
</div>
<div id="series">
<form action="{% url "add_files" %}" method="post">
{% csrf_token %}
{% bootstrap_form addserie %}
{% buttons %}
<button type="submit" class="btn btn-primary" id="submitbutton" name="serie">
{% bootstrap_icon "star" %} Ajouter
</button>
{% endbuttons %}
</form>
</div>
my forms :
class Addseries(forms.ModelForm):
class Meta:
model = series
exclude = ('nbTelechargement','datedepot')
class Addfilms(forms.ModelForm):
class Meta:
model = series
exclude = ('nbTelechargement','datedepot')
class searchbar(forms.Form):
motclef=forms.CharField(max_length=15,widget=forms.TextInput(attrs={'placeholder': 'Search...','style':'background :#ededef url("/static/image/search.png") no-repeat;background-size: auto 90%;'}))
categorie=forms.ChoiceField(choices=(('films', 'films'),
('séries', 'séries'),
('jeux', 'jeux'),
('logiciels', 'logiciels'),
('livres', 'livres'),
('musiques', 'musiques')))
I see several things:
It's not a Django issue but a HTML one:
When a user submits a form, he/she submits only form.
Django receives in request.POST only the data sent by one form.
Your forms share the same fields' names.
Addseries.nbTelechargement and Addfilms.nbTelechargement will have the same key in request.POST
I just forgot to add enctype="multipart/form-data" in my form balise.
My request.FILES was empty because of that.
So my form was unvalid because of that.

Django form fields as template variables

The main question is if it is possible to specifify specific form fields at different given locations in your html template in any smooth way. e.g. {{ form.password }} However, that does not seem to work. (I swear that I have seen this somewhere, but I just can't find it anymore on the internet)
My view for signing up new users is inheriting from UserCreationForm and looks kind of like this:
views.py
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = UserCreationForm()
return render(request, 'core/authentication/registration_form.html', {'form': form})
It sends this form straight to the template registration_form.html, this is how I wish it worked:
<form class="form" method="POST" action="">
<div class="card-body">
<div class="input-group form-group-no-border">
<span class="input-group-addon">
<i class="now-ui-icons users_circle-08"></i>
</span>
{{ form.first_name }}
</div>
</div>
This is how it actually works (for now):
<form class="form" method="POST" action="">
<div class="card-body">
<div class="input-group form-group-no-border">
<span class="input-group-addon">
<i class="now-ui-icons users_circle-08"></i>
</span>
<input type="text" class="form-control" placeholder="First Name...">
</div>
</div>
This might be a stupid question, but oh well I am curious.
Thank you in advance
If i've understood your question correctly, here is how django says you should render django form fields manually.
{{ form.non_field_errors }} # here django renders errors which do not belong to any field
<div>
{{ form.field_1.errors }} # here django renders errors which belong to field_1
{{ form.field_1.label_tag }} # label element
{{ form.field_1 }} # input element
</div>
# some html
<div>
{{ form.field_2.errors }}
{{ form.field_2.label_tag }}
{{ form.field_2}}
</div>
You can read this here in the lower half.
Each field ( each label, input, error elements ) can be rendered with custom classes and widgets.