Change existing model data with form - python

I am trying to implement a view that displays a form to capture data and a table with the captured data of a user. The table has a form with two buttons per row, either submitting "change" or "delete" together with the object id of the object in the given table row, using POST.
My Django view looks like this:
def captureData(request):
form = MyForm(request.POST or None)
if request.method == "POST":
if 'delete' in request.POST:
# User hits "Delete" button in displayed objects table.
try:
del_object = MyObject.objects.filter(user = request.user).get(id = request.POST['delete'])
del_object.delete()
except:
# Do something ...
return redirect('captureData')
elif 'change' in request.POST:
# User hits "Change" button in displayed objects table.
ch_object = MyObject.objects.filter(user = request.user).get(id = request.POST['change'])
form = MyForm(instance = ch_object)
if form.is_valid():
form.save()
return redirect('captureData')
else:
# New data to be added to the database.
if form.is_valid():
new_object = form.save(commit = False)
new_object.user = request.user
new_object.save()
return redirect('captureData')
objects = Object.objects.filter(user = request.user)
context = {'form': form, 'objects': objects}
return render(request, 'myTemplate.html', context)
This is how the myTemplate.html looks like:
{% extends "base.html" %}
{% block content %}
<h3>Data capturing</h3>
<p>
<!-- First form, responsible for capturing data -->
<form method="POST" action=""> {% csrf_token %}
{{form}}
<input type ='submit' value='Save'/>
</form>
</p>
<h3>Captured data</h3>
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th colspan="2">Actions</th>
</tr>
</thead>
<tbody>
{% for object in objects %}
<tr>
<td>{{forloop.counter}}</td>
<td>{{object.name}}</td>
<td>{{object.address}}</td>
<td>{{object.city}}</td>
<!-- Second form (per row), responsible for submitting a "delete" or "change" -->
<form action="" method="POST">{% csrf_token %}
<td>
<button type="submit" value="{{object.id}}" name="change" id="object{{object.id}}">Change</button>
</td>
<td>
<button type="submit" value="{{object.id}}" name="delete" id="object{{object.id}}">Delete</button>
</td>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
The "delete" part works fine. The problem is the "change" part. It successfully populates the form with the selected objects data, but when I hit the capture from submit button it runs into the else: clause resulting in a new data row or an error, if the data already exists. The reason for this is obvious: The new POST data does not contain the "change" marker anymore.
How can I separate the elif: part from the else: part?

Related

How to render multiple update forms in Django

here is my problem.
I have a list of objects that I display in a table and all works just fine except that I would like to edit them inside a modal and submit them using AJAX.
I though that it was a simple idea to render, for each row, a form with the inputs pre-filled and then submit the selected form with AJAX.
I wonder if there is a relatively simplified way to render the UpdateForm without writing manually all the input fields.
Something like this:
<table>
{% for transaction in transactions %}
<tr>
<td>{{ transaction.date|date:"d.m.Y" }}</td>
<td>{{ transaction.amount }}</td>
<td>
Edit
<div class="modal" id="edit{{ transaction.id }}">
{{ transaction_form }}
</div>
</td>
<tr>
{% endfor %}
</table>
But how can I pass the form from the view?
The way I'm currently doing it is that when the user click on edit the page refresh and the modal is displayed with the form prefilled but it is (a) slow to open and (b) I don't think it is a nice way to do it.
This is my current code
views.py
class ProjectDetailView(DetailView):
model = Project
template_name = "template.html"
context_object_name = "project"
def get_transactions(self):
transactions = Transaction.objects.filter(project=self.get_object())
return transactions
def get_transaction_form(self):
form = TransactionForm()
if self.request.POST:
form = TransactionForm(self.request.POST)
elif 'edit_entry' in self.request.GET:
form = TransactionForm(instance=self.get_entry())
return form
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['transactions'] = self.get_transactions()
context['transaction_form'] = self.get_transaction_form()
return context
template.html
<table>
{% for transaction in transactions %}
<tr>
<td>{{ transaction.date|date:"d.m.Y" }}</td>
<td>{{ transaction.amount }}</td>
<td>
Edit
</td>
<tr>
{% endfor %}
</table>
<div class="modal" id="edit-modal">
{{ transaction_form }}
</div>
<script>
{% if 'edit_entry' in request.GET %}
$('#edit-modal').modal('show')
{% endif %}
</script>
Thank you for any feedback
This solution needs you work with Javascript to do that,
when the user clicks 'Edit' for an object on your page,
you send AJAX request (using Fetch API or Jquery) to your view,
The view will return HTML of the form and you put this HTML in the modal's body
Show the modal with an action button to submit the form.
As the user clicks submit, your code submits the form through Ajax, you can use Formdata or AjaxForm for that, the view which return an JSON or HTML which indicates if the data is saved successfully or not.
The problem I'm not a Class-Based View guy so I can't give you specifics from Django side.

.getlist() is not returning anything in django / html form checkbox input

I have a 2 forms within my list view for a model. The first one is a search bar which works fine with GET and the next is to select items displayed and collect them to edit. I haven't gotten to the editing because I cannot get a list of the selected objects.
View.py
#login_required
def ex_list(request):
context = {}
if request.GET:
#code for search bar
if request.POST:
selected_values = request.POST.getlist('exlist[]')
print(selected_values)
return render(
request,
'ex/list.html',
context
)
List.html
<form method="POST" action="">
{% csrf_token %}
<table id="exs" class="table table-hover table-striped">
<tbody>
{% for ex in exs %}
<tr>
<td>
<center><input type="checkbox" name="exlist[]" value="{{ex.esid}}"/></center>
</td>
{% endfor %}
<input type="submit" class="btn btn-primary" value="Edit Selected Items" name="edit">
</form>
Although I have print(selected_values), all that is being returned is empty brackets {}. I at least know that we are getting inside of the if statement.
Firstly, in your list.html you haven't specified action and just left it blank
change it to
<form method = "post" action = "{% url 'ex_list' %}">
...
</form>
Also, you are passing empty context to the rendering template that's why you are getting {}
change it to
context = {
"selected_values" = selected_values,
}
return render(request, "...", context)

Multiple button in Django: Accept and Reject

I am new to Django. I am working on a project where I want accept and reject button and whenever client click on the respective button that object will go into the accept or reject template. I have no idea how can I do this.
This is my .html file which is displaying all the objects and have a accept and reject button:
<div class="body table-responsive">
<form id="form" method="POST" action = "{% url 'admin_team_detail' %}">
{% csrf_token %}
<table class="table table-hover">
<thead>
<tr>
<th>S No.</th>
<th>COMPANY NAME</th>
<th>TEAM MEMBER</th>
<th>EMAIL</th>
<th>STATUS</th>
<th><center>#</center></th>
</tr>
</thead>
<tbody>
{%for team in object%}
<tr>
<th scope="row"> {{ forloop.counter }}</th>
<td>{{team.company_name}}</td>
<td>{{team.team_member}}</td>
<td>{{team.email}}</td>
<td>-</td>
<td><center><input type="submit" value="accept" name="accept">
<input type="submit" value="reject" name="reject"></center></td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
Here is views.py:
def admin_team_detail(request):
obj= Create_Team.objects.all()
print(request.method)
if request.method == 'POST':
if 'reject' in request.POST :
Create_Team.status = 'reject'
else:
Create_Team.status = 'accept'
Create_Team.save()
return render(request, "admin/team-details.html", {"object": obj})
This is rendering all the objects from database and displaying on the website.
I know that I have to make two templates for accept and reject but I don't know how it will take the objects that have a accept or reject response.
And I also want that if client click on the button then that response will be saved in the database.
And I also want to know that whether I have to add a field in my model.py for status.
First your two buttons should send the desired value to your views.py and one hidden input in order to pass the team id
<input type="submit" value="reject" name="status">
<input type="submit" value="accept" name="status">
<input type="hidden" name="id" value={{ team.id }}>
Next, in your views.py
def admin_team_detail(request):
if request.method == 'POST':
# First, you should retrieve the team instance you want to update
team = Create_Team.objects.get(id=request.POST('id'))
# Next, you update the status
if request.POST.get('status'):
team.status = request.POST.get('status')
team.save()
Note: this example assumes your Team model has a status field in order to store the reject/accept value.
class Team(models.Model):
# You existing fields...
status = models.CharField(max_length=30)
First You need to create a form for each object inside the template.
{%for team in object%}
<form method="POST">
{%csrf_token%}
<input type="hidden" name="team_id" value={{ team.id }}>
<input type="submit" value="reject" name="status">
<input type="submit" value="accept" name="status">
</form>
{% endfor %}
Now in View.py, you need to do something like this:
def admin_team_detail(request):
if request.method == 'POST':
# I am assuming Create_Team is your model where all team's are present.
team = Create_Team.objects.get(id=request.POST.get("team_id"))
team.status = request.POST.get("status")
team.save()

How to add forms to a dictionary upon submission

I am creating a shopping cart as a part of the application I'm building.
I am trying to figure out how to add a form submission to a dictionary (I think this is what I need to do).
So for example this is what the page would look like(This is just test data).
Upon Clicking the add button I want the item name and price to populate in the Orders table to the right of the Pricing table(To start off). Once all orders have been added I'd click the Order button and that will order the added items in some type of list to the database using sqlalchemy. Now I feel strongly and I may be wrong that upon submitting form using add button that the form needs to be added to a dictionary. I just don't know how to save that dictionary and where that dictionary should be stored? Here is my code as of now.
routes.py
I tried putting the dictionary with in the route function but a single instance is created on each submission. So nothing is really being saved to dictionary.
#app.route('/equipment', methods=['POST', 'GET'])
def equipment():
form = OrderEquipmentForm()
eq = equipment_prices
# Tried to store forms in this dictionary but it look like a new instance
# is created on every form submission
ordersss = {}
if form.validate_on_submit():
ordersss[form.Type.data] = form.Price.data
print(form.Type.data, form.Price.data)
print(ordersss)
return redirect(url_for('equipment'))
return render_template('equipment.html', name='equipment', eq=eq, form=form)
#app.route('/equipment/cart', methods=['GET, POST'])
def cart():
return render_template('cart.html', name='cart')
Forms.py
Not sure if there needs to be function with in the actual form that adds the values to a dictionary
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
class AddEquipmentForm(FlaskForm):
Type = StringField('Type of Equipment',DataRequired())
Price = StringField('Price',DataRequired())
submit = SubmitField('Add equipment')
class OrderEquipmentForm(FlaskForm):
Type = StringField()
Price = StringField()
Order = SubmitField('Order')
# Should Dictionary go here?
# Not sure
def dict():
dict = {}
dict[Type] = Price
equipment.html
I would like to loop the element of the dictionary with in the Orders Table, if a dictionary is needed.
{% extends 'base.html' %}
{% block content %}
<div class="row">
<div class="col-6-sm">
<h1>Pricing</h1>
<table class='border'>
<thead class='border'>
<th style="width:200px;">Equipment</th>
<th style="width:200px; text-align:center;">Price</th>
<th></th>
</thead>
{% for quip in eq %}
<form method="post">
{{ form.hidden_tag() }}
<tr class ='border'>
<td>{{ quip }}</td>
<td style="text-align:center;"> <strong>${{ eq[quip] }}</strong></td>
<!-- Here I'm adding StringFields from the form but hiding them so they aren't displayed so I can submit the data somehow, hopefully to a dictionary. -->
<td style="display:none;">{{ form.Type(value=quip)}}</td>
<td style="display:none;">{{ form.Price(value=eq[quip]) }}</td>
<td><button class='btn btn-primary' type="submit">Add</button></td>
</tr>
</form>
{% endfor %}
</table>
</div>
<div class="col-6-sm">
<h1>Orders</h1>
<table>
<!-- This is where a loop of the dictionary elements of the items added would go -->
<tr>
<td></td>
<td></td>
</tr>
<button style='float:right' type="button" name="button" class='btn btn-info'>Order</button>
</table>
</div>
</div>
{% endblock %}

Drop down lists not populating in DB in Django Forms on click of submit button

I have a table inside form. It looks like below:
{% extends "base.html" %}
{% block title %}Title{% endblock title %}
{% block content %}
<form actions="" method="post">
{% csrf_token %}
<table>
<table border = "1" cellpadding = "10" cellspacing = "10" bordercolor = "green">
<tr>
<th>numbers</th>
<th>Extension</th>
<th>Vendor</th>
</tr>
{% for number in numbers %}
<tr>
<td>{{ number }}</td>
<td class = "select">Select Extension
<select name="extensions">
{% for obj in sipextensionsets %}
<option value={{obj.sip_extension}}>{{ obj.sip_extension }}</option>
{% endfor %}
</select>
</td>
<td>vendor</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="save"/>
</form>
{% endblock content %}
My forms.py is below:
from django import forms
from .models import column
class didsForm(forms.ModelForm):
class Meta:
model = column
fields = ('extension')
My views.py is below
def saveintodb(request):
try:
instance = coloumn.objects.get(pk=1)
except:
instance = coloumn(pk=1)
instance.save()
if request.method == 'POST':
dids_form = didsForm(data=request.POST['extensions'], instance=instance)
if dids_form.is_valid():
dids_form.save()
messages.success(request, "Settings updated. Please apply settings.")
else:
messages.error(request, "Error: Invalid settings.")
else:
dids_form = didsForm(instance=instance)
return render(request, 'dids/index.html', {'dids_form': dids_form})
In the table, there is a drop down (select tag). I want to save the data into database when user selects something from dropdown and clicks on save button. I know I have mistaken somewhere in views.
You're doing a few things wrong here, unfortunately.
The main problem is that you're passing request.POST['extensions'] as the data argument to your form on POST; but that argument is expecting the whole POST, not a single field.
Linked to that is that you have not used the same name for the field in the model and the field in the form. Although you say in your comment that this is intentional, there doesn't seem to be a reason for it, and it's breaking things. Give them the same name.
Thirdly, you aren't letting Django populate the form, or show any errors when it's not valid. You shouldn't be explicitly passing sipextenionset (although you actually don't seem to be passing that at all, so I'm not sure where it's coming from), and you certainly shouldn't be explicitly iterating. You should let Django display the field:
<td>{{ number }}</td>
<td class="select"><label for="id_extension">Select Extension</label>
{{ form.extension }}
</td>
Finally, I can't at all understand what you are doing with that outer for loop through numbers; you will end up with several values for extension, which is not expected by your form, your model, or your view.

Categories