Django/Python - remove row in sqlite3 database with form button - python

I want to have a delete button to delete a row in my sqlite3 database. I'm almost there but I'm not sure what I should add to send the ID from my html of the row to my views.py. This is what I have:
mailindex.html
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
Manage
<button type="submit" name="deletemail" value="deletemail" class="btn btn-secondary btn-sm">Delete</button>
</div>
</form>
views.py
class MailboxView(generic.ListView):
extra_context = {"mailbox_page": "active"}
model = MailMessage
context_object_name = 'mails'
template_name = 'core/mailbox/mailindex.html'
def post(self, request):
# if 'deletemail' in self.request.POST:
if request.POST.get('deletemail'):
mail = MailMessage.objects.get(pk=13)
mail.delete()
return HttpResponseRedirect(self.request.path_info)
It works, in a sense that when I push the delete button it deletes email with ID = 13. Which is logical as I put no. 13 there. I would like to replace '13' with the mail.id, but I'm not sure how to do this. I hope it is possible: I would prefer it to be as simple as possible, so to not create an extra url, but again don't know if this is possible...

Use deletemail tag in type:hidden another input not button.

Try this
<div class="form-group">
Manage
<input type="hidden" name="deletemail" value="13">
<button type="submit" class="btn btn-secondary btn-sm">Delete</button>
</div>

Related

Need to show result on the same page - Django

I'm creating a password generator app. The app is working and stores the value on db.
The problem is whenever I refresh, the form resubmits and takes the previous value and stores.
Also, I want to show the email and password on the same page.
Whenever I refresh, I want to show an empty form with empty fields.
Views.py
def home(request):
if request.method=='POST':
inputemail = request.POST.get('InputEmail')
gen = ''.join(random.choices((string.ascii_uppercase+string.ascii_lowercase+string.digits+string.punctuation), k=10))
newpass = Item(email=inputemail,encrypt=gen)
newpass.save()
return render(request,'home.html',{"gen":gen})
return render(request,'home.html',{})
Home.html
<form method = 'post' id='pass-form' >
{% csrf_token %}
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Email address</label>
<input type="email" class="form-control" name="InputEmail" >
<div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
</div>
<button type="submit" name = "submit" class="btn btn-primary">Generate Password</button><br><br>
</form>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Generated Password</label>
<input type="text" id="InputPassword" name = "genpassword" value = {{gen}} >
</div>
Urls.py
urlpatterns = [
path('',views.home,name='home'),
]
According to docs:
you should always return an HttpResponseRedirect after successfully dealing with POST data. This tip isn’t specific to Django; it’s good web development practice in general.
So you should make another page to show generated password, which will take submitted instance id of Item model created in home view so:
def home(request):
if request.method=='POST':
inputemail = request.POST.get('InputEmail')
gen = ''.join(random.choices((string.ascii_uppercase+string.ascii_lowercase+string.digits+string.punctuation), k=10))
newpass = Item(email=inputemail,encrypt=gen)
newpass.save()
return redirect('success', args=(newpass.pk))
return render(request,'home.html',{})
def success(request, pk):
item_obj = get_object_or_404(Item, pk=pk)
return render(request,'success.html', {'gen':item_obj.encrypt})
urls.py
urlpatterns=[
path('',views.home,name='home'),
path('success/<int:pk>/',views.success,name='success')
]
success.html
<body>
<h2>The form is successfully submitted.</h2>
<br>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Generated Password</label>
<input type="text" id="InputPassword" name="genpassword" value={{gen}} >
</div>
Again go to password generator page.
</body>
Another possible solution
You can make email field required in Html form and then hard refresh the page after submitting the form using Javascript's submit event so the template:
<form method='POST' id='pass-form'>
{% csrf_token %}
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Email address</label>
<input type="email" class="form-control" name="InputEmail" required>
<div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
</div>
<button type="submit" class="btn btn-primary">Generate Password</button><br><br>
</form>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Generated Password</label>
<input type="text" id="InputPassword" name = "genpassword" value ={{gen}} >
</div>
<script type='text/javascript'>
let form = document.getElementById('pass-form');
addEventListener('submit', (event) => {
location.reload(true); // hard refreshed
console.log('hard refreshed')
});
</script>
Note: Then also there are certain browsers like Microsoft Edge which gives pop up as Resubmit the form? in which they mention The page you're looking for used information that you entered. Returning to the page might trigger a repitition of any action you took there. Do you want to continue?
The moment you click on continue it creates duplicacy of records, so I think as docs mentions the first approach is better.

I need to update the database how can I do it?

I have been trying to create a to do list app and there has been no problems until when i was adding an edit button, when i press the edit button, it shows the edit page with the text that has to be edited but the submit button that is suposed to change the database is not working, I think I need to add something to the views.py file but I dont know what.
viws.py
def edit(request, id):
created_items = Create.objects.get(id=id)
return render(request, 'my_app/edit.html', {"created_items": created_items})
urls.py
urlpatterns = [
path('edit/<int:id>/', views.edit, name='edit'),
]
models.py
class Create(models.Model):
added_date = models.DateTimeField()
text = models.CharField(max_length=200)
edit.html
{% extends 'index.html' %}
{% block body %}
<div align="center">
<h1>Edit your post!</h1>
<div class="container form-group">
<h1>↓</h1>
<form method="POST">{% csrf_token %}
<textarea class="form-control" name="content" id="id" rows="3" style="text-align: center;">{{ created_items.text }}</textarea>
<button type="submit" class="btn btn-outline-success" style="margin-top: 5px;">Submit</button>
</form>
</div>
</div>
{% endblock %}
You will send POST request when you click submit and need to catch that request in some function like:
if request.method == 'POST':
edited_text = request.POST.get('text') ## 'text' might be changed. I don't know how you handle the request.
related_id = request.POST.get('id') ## You need to take updated id. (somehow?)
Create.objects.filter(id=related_id).update(text=edited_text) ## That will do the job.
Hope it helps,

Passing variable with POST in django

Hi im trying to pass a name from a form to a view in django using POST. There are no errors in the execution but its passing nothing from the template and dont know if i doing something wrong here. Im starting with django so i can have newbie errors. If u need more information tell me pls.
Views.py
def crear_pdf(request):
empresa_selec = ""
form = EmpModelForm()
if request.method == 'POST':
form = EmpModelForm(data=request.POST)
if form.is_valid():
empresa_selec = form.cleaned_data['nombre']
#"empresa_selec" that's the empty variable
Models.py
class Empresa_modelo(models.Model):
nombre = models.CharField(max_length=100,blank=True,null=True)
Forms.py
class EmpModelForm(forms.ModelForm):
class Meta:
model = Empresa_modelo
fields = ["nombre"]
template.html
<div class="container-fluid">
<form method="POST" enctype="multipart/form-data" action="{% url 'crear_pdf' %}">{% csrf_token %}
<p>Empresa</p>
<input type="text" name="empresa">
<br>
<button type="submit">Subir</button>
</form>
<br>
<a class="btn btn-primary" href="{% url 'crear_pdf' %}">Atras</a>
</div>
You haven't got a field called nombre in your template; you only have empresa.
That's presumably because you don't ouput your EmpModelForm in the template. You don't show your render call in the view, but assuming you pass it as form, you should just do {{ form.as_p }} in the template.
Try using:
<input type="text" name="nombre">
There is no field named empresa.
Had a look at your code,there are a couple of issues.First you are not using the model form defined in your forms.py file in your template. Second you have defined an input text box with the name that you are not referring in your views. Either use the model form or use the same name of your input text box in your views.
def crear_pdf(request):
empresa_selec = ""
form = EmpModelForm()
if request.method == 'POST':
form = EmpModelForm(data=request.POST)
if form.is_valid():
empresa_selec = form.cleaned_data['nombre']
else:
return render(request,"template.html",{"form":form})
And in your template you can edit as such:
<div class="container-fluid">
<form method="POST" enctype="multipart/form-data" action="{% url 'crear_pdf' %}">{% csrf_token %}
{{ form.as_p }}
<br>
<button type="submit">Subir</button>
</form>
<br>
<a class="btn btn-primary" href="{% url 'crear_pdf' %}">Atras</a>
</div>
Hope this helps.

django modelformset_factory doesn't include actual forms

I've been trying to follow tutorials and other SO questions and have a modelformset_factory that's displaying a list of what looks like forms in the html, but it turns out they're not actual forms.
html that gets displayed:
<div ='container'>
<div class='row'><tr><th><label for="id_form-0-config_key">Config key:</label></th><td><input id="id_form-0-config_key" maxlength="63" name="form-0-config_key" type="text" value="ClientMustVerify" /></td></tr>
<tr><th><label for="id_form-0-config_value">Config value:</label></th><td><input id="id_form-0-config_value" maxlength="63" name="form-0-config_value" type="text" value="TRUE" /><input id="id_form-0-id" name="form-0-id" type="hidden" value="3" /></td></tr> <input type="submit" value="Update" /></div>
<div class='row'><tr><th><label for="id_form-1-config_key">Config key:</label></th><td><input id="id_form-1-config_key" maxlength="63" name="form-1-config_key" type="text" value="Auditing" /></td></tr>
<tr><th><label for="id_form-1-config_value">Config value:</label></th><td><input id="id_form-1-config_value" maxlength="63" name="form-1-config_value" type="text" value="FALSE" /><input id="id_form-1-id" name="form-1-id" type="hidden" value="4" /></td></tr> <input type="submit" value="Update" /></div>
<div>
notice there is no form tag anywhere. working backwards, here's the excerpt from the template:
<div ='container'>
{% for form in formset %}
<div class='row'>{{form}} <input type="submit" value="Update" /></div>
{% endfor %}
<div>
yes, I added the submit button manually hoping to get these to work, but of course if there isn't a form tag, then the submit button won't do anything.
views.py:
from limbo.models import serverConfig
from django.forms import modelformset_factory
from django.forms import formset_factory
def editServer(request):
result = serverConfig.objects.values()
myConfigs = [entry for entry in result]
finalFormSet = modelformset_factory(serverConfig, exclude=('id',), extra=0)
#other lines
return render(request, 'limboHtml/ServerConfiguration.html', {'formset': finalFormSet, 'SubmitMessage': '', 'CurrentConfigs': myConfigs})
forms.py:
class serverForm(ModelForm):
class Meta:
model = serverConfig
fields = ['config_key', 'config_value']
def __init__(self, *args, **kwargs):
super(serverForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if instance and instance.pk:
self.fields['config_key'].widget.attrs['readonly'] = True
self.fields['config_key'].widget.attrs['disabled'] = True
and models.py:
class serverConfig(models.Model):
config_key = models.CharField(max_length=63)
config_value = models.CharField(max_length=63)
I tried using finalFormSet = formset_factory(serverForm, extra=0) at one point, but then I just got no content in the html...
As described in the formset documention you must add the form tag manually. This is not very different from what you do when displaying a single form.
It appears that you are iterating through the formset and displayig them one by one. That means you must also add the management form
<form method="post" action="">
{{ formset.management_form }}
<div ='container'>
{% for form in formset %}
<div class='row'>{{form}} <input type="submit" value="Update" /></div>
{% endfor %}
<div>
</form>
Or you will get errors about a missing or misconfigured management form.
Note that it does not include the tags, or a submit button. We’ll have to provide those ourselves in the template.
Read more: Working with Forms: Building a form in Django
The reason you are not getting the <form> tag is because from a logical point of view a form validation can be handled anywhere in your application. That's why you need to specify the form tag explicitly with the target url (good to use reverse(view_name)), method and other parameters.

List item template Django

I'm dealing creating a template on Django to show a list of items with 2 buttons that make actions.
My form class it's:
class AppsForm(forms.Form):
def __init__(self, *args, **kwargs):
policiesList = kwargs.pop('policiesList', None)
applicationList = kwargs.pop('applicationList', None)
EC2nodesList = kwargs.pop('amazonNodesList', None)
super(AppsForm, self).__init__(*args, **kwargs)
self.fields['appsPolicyId'] = forms.ChoiceField(label='Application Policy', choices=policiesList)
self.fields['appsId'] = forms.ChoiceField(label='Application', choices=applicationList)
self.fields['ec2Nodes'] = forms.ChoiceField(label='Amazon EC2 Nodes', choices=EC2nodesList)
Now, I do the form with:
<form method="post" action="" class="form-inline" role="form">
<div class="form-group">
{% for field in form %}
{ field.label }}: {{ field}}
{% endfor %}
</div>
{% csrf_token %}
<input type="submit" class="btn btn-default btn-success" name="deployButton" value="Deploy"/>
<input type="submit" class="btn btn-default btn-danger" name="undeployButton" value="Undeploy"/>
And the result it's:
Application Policy - Choicefield ; Application - Choicefield ; Amazon EC2 Nodes - Choicefield [Button Deploy] [Button Undeploy]
And what I'm looking for it's a way to render the form and show the list like this:
Application Policy - Choicefield ; Application - Choicefield [Button Deploy] [Button Undeploy]
Amazon EC2 Nodes - Choicefield [Button Deploy] [Button Undeploy]
<more items if I add them in forms.py...>
How I can get the proper way to render like that?
Thanks and regards.
You just need to change the code a bit is all:
{% for field in form %}
{ field.label }}: {{ field}}
<input type="submit" class="btn btn-default btn-success" name="deployButton" value="Deploy"/>
<input type="submit" class="btn btn-default btn-danger" name="undeployButton" value="Undeploy"/>
<br />
{% endfor %}
So this will create a new line for each of the field.label and field variables with their own button. One thing to caution against though, if you try and assign ID's to the buttons they will have to be different or you'll get errors. Also, submission may be a bit weird with code such as this but it depends on the rest of your application. Either way, this will give you the desired format.

Categories