i have a problem when make ajax request to the server to add product to the card using django and jquery,
this the URLs here:
path('add_to_cart/', cartView.add_to_cart, name="add_to_cart")
here the jquery code:
$(document).ready(function () {
$('.addToCartBtn').click(function (e) {
console.log("jjjj")
e.preventDefault();
var product_id = $(this).closest('.product_data').find('.prod_id').val()
var product_qty = $(this).closest('.product_data').find('.qty-input').val()
var token = $('input[name=csrfmiddlewaretoken]').val()
console.log(token)
console.log(product_id)
console.log(product_qty)
$.ajax({
method: 'POST',
url: 'add_to_cart',
data: {
'product_id' : product_id,
'product_qty' : product_qty,
csrfmiddlewaretoken: token
},
success: function(res) {
console.log(res.status)
alertify.success(res.status)
}
})
})
});
and here is the view django code:
from django.http.response import JsonResponse
from django.shortcuts import render, redirect
from django.contrib import messages
from store.models import Product, Cart
def add_to_cart(request):
if request.method == 'POST':
if request.user.is_authenticated:
prod_id = request.POST.get('product_id')
product_check = Product.objects.get(id=prod_id)
if product_check:
if Cart.objects.filter(user=request.user.id, product_id=prod_id):
return JsonResponse({'status': 'Product Already in the Cart'})
else:
prod_qty = int(request.POST.get('product_qty'))
if product_check.quantity >= prod_qty:
Cart.objects.create(user=request.user, product_id=prod_id, product_quantity=prod_qty)
return JsonResponse({'status': 'Product Added Successfully'})
else:
return JsonResponse({'status': "only" + str(product_check.quantity) + "is Available"})
else:
return JsonResponse({'status': 'No Such Product Found'})
else:
return JsonResponse({'status': 'Login To Continue'})
return redirect('/')
and here is the view.html when add to card button exist:
<section style="background-color: #eee;">
{% csrf_token %}
<div class="container py-5 product_data">
<div class="row justify-content-center mb-3">
<div class="col-md-12 col-xl-10">
<div class="card shadow-0 border rounded-3">
<div class="card-body">
<div class="row">
<div class="col-md-12 col-lg-3 col-xl-3 mb-4 mb-lg-0">
<div class="bg-image hover-zoom ripple rounded ripple-surface">
<img src="{{ product.product_image.url }}"
class="w-100"/>
<a href="#!">
<div class="hover-overlay">
<div class="mask"
style="background-color: rgba(253, 253, 253, 0.15);"></div>
</div>
</a>
</div>
</div>
<div class="col-md-6 col-lg-6 col-xl-6">
<h1>{{ product.name }}</h1>
<div class="d-flex flex-row">
<div class="text-danger mb-1 me-2">
<i class="fa fa-star"></i>
<i class="fa fa-star"></i>
<i class="fa fa-star"></i>
<i class="fa fa-star"></i>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-2">
<div class="input-group">
<span class="input-group-btn">
<input type="hidden" value="{{ product.id }}" class="prod_id">
<button type="button" class="quantity-left-minus btn btn-primary btn-number"
data-type="minus" data-field="">
<span class="glyphicon glyphicon-minus"></span>
</button>
</span>
<input type="text" id="quantity" name="quantity"
class="form-control input-number qty-input" value="0" min="1" max="10">
<span class="input-group-btn">
<button type="button" class="quantity-right-plus btn btn-primary btn-number"
data-type="plus" data-field="">
<span class="glyphicon glyphicon-plus"></span>
</button>
</span>
</div>
</div>
</div>
</div>
<div class="mt-1 mb-0 text-muted small">
{{ product.description }}
</div>
</div>
<div class="col-md-6 col-lg-3 col-xl-3 border-sm-start-none border-start">
<div class="d-flex flex-row align-items-center mb-1">
<h4 class="mb-1 me-1">{{ product.selling_price }}</h4>
<span class="text-danger"><s>{{ product.original_price }}</s></span>
</div>
{% if product.trending %}
<h6 class="text-center badge bg-danger" style="font-size: 16px">Trending</h6>
{% endif %}
<div class="d-flex flex-column mt-4">
{% if product.quantity > 0 %}
<button class="addToCartBtn btn btn-primary btn-sm " type="button">Add To Cart</button>
{% endif %}
<button class="btn btn-outline-primary btn-sm mt-2" type="button">
Add to wishlist
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
this is the error message when I click on the button to make a ajax call:
ValueError: The view store.views.product_details didn't return an HttpResponse object. It returned None instead.
[03/May/2022 21:11:11] "POST /category/mobile/add_to_cart HTTP/1.1" 500 65574
I think, it is throwing error the view return None instead since you haven't redirected it inside the if condition where you are handling POST request.
Redirect it inside the if condition.
Try this:
def add_to_cart(request):
if request.method == 'POST':
if request.user.is_authenticated:
prod_id = request.POST.get('product_id')
product_check = Product.objects.get(id=prod_id)
if product_check:
if Cart.objects.filter(user=request.user.id, product_id=prod_id):
return JsonResponse({'status': 'Product Already in the Cart'})
else:
prod_qty = int(request.POST.get('product_qty'))
if product_check.quantity >= prod_qty:
Cart.objects.create(user=request.user, product_id=prod_id, product_quantity=prod_qty)
return JsonResponse({'status': 'Product Added Successfully'})
else:
return JsonResponse({'status': "only" + str(product_check.quantity) + "is Available"})
else:
return JsonResponse({'status': 'No Such Product Found'})
else:
return JsonResponse({'status': 'Login To Continue'})
return redirect('/')
Related
I have a chat code in which I want to display and suggest only those users with whom there has already been a correspondence, that is, both incoming and outgoing messages, and not all registered users.
html code:
<div class="container" style="height: 75%;">
<div class="card bg-dark h-100 border-light">
<div class="card-body h-100">
<div class="row h-100">
<div class="col-md-4 border-right h-100">
<div class="list-group bg-dark" id='user-list'>
{% for u in users %} {% if not u.id == 1 and not u.id == user.id %}
<a class="list-group-item {% if u.id != chat_id %}bg-dark{% else %}bg-primary{% endif %} text-white" href="{% url 'chat-home' %}?u={{u.id}}">
<div>
<p>{{u.first_name}} {{u.last_name}} ({{u.username}})</p>
</div>
</a>
{% endif %} {% endfor %}
</div>
</div>
<div class="col-md-8 h-100">
{% if not chat_id > 0 %}
<div class="h-100 d-flex flex-column justify-content-center align-items-center">
<h3>Начните общение!</h3>
<p><small class="text-muted">Выберете человека, чтобы написать ему.</small></p>
</div>
{% else%}
<div id="chat-box-field" class="h-100">
<div class="chat-box" style="height:80%">
{% for chat in chats %} {% if chat.user_from == user %}
<div class="p-2 w-100 d-flex justify-content-end">
<div class=" chat-bubble ml-2 mb-2 bg-primary text-light rounded" data-id="{{chat.id}}">
<p>{{chat.message}}</p>
<div class="d-flex justify-content-between"><small>Ты</small> <small>{{chat.date_created|date:"M-d-Y H:i"}}</small></div>
</div>
</div>
{% else %}
<div class="p-2 w-100 d-flex justify-content-start">
<div class="chat-bubble mr-2 mb-2 bg-light text-dark rounded" data-id="{{chat.id}}">
<p>{{chat.message}}</p>
<div class=" d-flex justify-content-between"><small>От</small> <small>{{chat.date_created|date:"M-d-Y H:i"}}</small></div>
</div>
</div>
{% endif %} {% endfor %}
</div>
<div class="chat-box-form border-top p-2" style="height:20%">
<div class="w-100 h-100">
<form action="" id="chat-submit" class="h-100 d-flex ">
<input type="hidden" name="user_from" value="{{ user.id }}">
<input type="hidden" name="user_to" value="{{ chat_id }}">
<div class="col-md-10 h-100">
<textarea name="message" id="" class="h-100 w-100 form-control" placeholder="Написать"></textarea>
</div>
<button class="button btn btn-primary h-100 w-100 justify-content-center align-items-center d-flex">Отправить</button>
</form>
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
views.py:
def get_messages(request):
chats = chatMessages.objects.filter(Q(id__gt=request.POST['last_id']),Q(user_from=request.user.id, user_to=request.POST['chat_id']) | Q(user_from=request.POST['chat_id'], user_to=request.user.id))
new_msgs = []
for chat in list(chats):
data = {}
data['id'] = chat.id
data['user_from'] = chat.user_from.id
data['user_to'] = chat.user_to.id
data['message'] = chat.message
data['date_created'] = chat.date_created.strftime("%b-%d-%Y %H:%M")
print(data)
new_msgs.append(data)
return HttpResponse(json.dumps(new_msgs), content_type="application/json")
def send_chat(request):
resp = {}
User = get_user_model()
if request.method == 'POST':
post =request.POST
u_from = UserModel.objects.get(id=post['user_from'])
u_to = UserModel.objects.get(id=post['user_to'])
insert = chatMessages(user_from=u_from,user_to=u_to,message=post['message'])
try:
insert.save()
resp['status'] = 'success'
except Exception as ex:
resp['status'] = 'failed'
resp['mesg'] = ex
else:
resp['status'] = 'failed'
return HttpResponse(json.dumps(resp), content_type="application/json")
models.py:
class chatMessages(models.Model):
user_from = models.ForeignKey(User,
on_delete=models.CASCADE,related_name="+")
user_to = models.ForeignKey(User,
on_delete=models.CASCADE,related_name="+")
message = models.TextField()
date_created = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.message
Please tell me how it can be implemented. I don't quite understand how to set a condition for checking for messagesm
You probably need to change the related name first on the model:
class chatMessages(models.Model):
user_from = models.ForeignKey(User,
on_delete=models.CASCADE,related_name="sent")
user_to = models.ForeignKey(User,
on_delete=models.CASCADE,related_name="received")
message = models.TextField()
date_created = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.message
And then to get all messages the user has received:
messages = request.user.received.all()
(Or User.objects.get(id=my_user_id).received.all())
To get all the users which the user has corresponded with, you can then do:
pk_list = messages.values("user_from__pk").distinct()
correspondents = get_user_model().objects.filter(pk__in=list(pk_list))
Sidenote:
In your views, you are getting the user model.
User = get_user_model()
But you don't do anything with it in this view:
def send_chat(request):
no form errors are showing up in my HTML template when the form is invalid. The form is placed within a carousel incase that's relevant.
I'm calling out individual form elements instead of rendering as {{form.as_p}}, errors where showing when this was the case.
The last item in the carousel is the password and if I leave this blank it will show a pop out that says "please fill in this field" but nothing more than that and only for that one field.
Views.py
def collapsecard(request):
if request.method == 'POST':
create_user_form = CreateUserForm(request.POST)
safezone_form = SafezoneForm(request.POST)
if create_user_form.is_valid() and safezone_form.is_valid():
user = create_user_form.save()
safezone = safezone_form.save(commit=False)
safezone.userid = user
safezone.useremail = user.email
safezone.save()
user = authenticate(username=create_user_form.cleaned_data['username'],
password=create_user_form.cleaned_data['password1'],
)
login(request,user)
api_key = 'XYZ'
api_secret = 'XYZ'
id = 'XYZ'
mailjet = Client(auth=(api_key, api_secret))
data = {
'Email': safezone.useremail,
'Action': "addnoforce"
}
result = mailjet.contactslist_managecontact.create(id=id, data=data)
print
result.status_code
print
result.json()
return redirect('safezoneaddedpage')
return render(request, 'V2maparonno_create_safe_zoneV2.html',
{'create_user_form': create_user_form, 'safezone_form': safezone_form})
else:
create_user_form = CreateUserForm()
safezone_form = SafezoneForm()
print(create_user_form.errors)
print(safezone_form.errors)
return render(request, 'V2maparonno_create_safe_zoneV2.html',
{'create_user_form': create_user_form, 'safezone_form': safezone_form})
Extract from HTML
<form action="" method="POST" class="form-control">
{% csrf_token %}
<div id="carouselExampleIndicators" class="carousel slide" data-interval="false" style="width: 100%">
<ol class="carousel-indicators">
<li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
<li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
<li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
<li data-target="#carouselExampleIndicators" data-slide-to="3"></li>
<li data-target="#carouselExampleIndicators" data-slide-to="4"></li>
</ol>
<div class="carousel-inner">
<div class="carousel-item active">
<div class="carousel-caption">
<h5>Drag the marker over your home</h5>
<div class="longlatinput">
{{ safezone_form.latitudecentre }}{{ safezone_form.longitudecentre }}
</div>
<button class="btn btn-sm btn-outline-primary" type="button" data-slide-to="1" data-target="#carouselExampleIndicators">Next</button>
</div>
</div>
<div class="carousel-item">
<div class="carousel-caption">
<h5>Give your safezone a name</h5>
<div class="form-inputs">
{{ safezone_form.name }}
</div>
<div class="name_space">
<button class="btn btn-sm btn-outline-primary" type="button" data-slide-to="2" data-target="#carouselExampleIndicators">Next</button>
</div>
</div>
</div>
<div class="carousel-item">
<div class="carousel-caption">
<h5>What email address should we send an alert to?</h5>
<div class="form-inputs">
{{create_user_form.email}}
</div>
<button class="btn btn-sm btn-outline-primary" type="button" data-slide-to="3" data-target="#carouselExampleIndicators">Next</button>
</div>
</div>
<div class="carousel-item">
<img src="https://pupaprojectawsbucket.s3.eu-west-2.amazonaws.com/Screenshot+2021-05-04+at+20.36.09.png" alt="..." style="width: 100%; height: 200px;">
<div class="carousel-caption">
<h5>Create your username</h5>
<div class="form-inputs">
{{create_user_form.username}}
</div>
<button class="btn btn-sm btn-outline-primary" type="button" data-slide-to="4" data-target="#carouselExampleIndicators">Next</button>
</div>
</div>
<div class="carousel-item">
<div class="carousel-caption">
<h5>Finally, set a password</h5>
<div class="form-inputs">
{{create_user_form.password1}}
</div>
<input class="btn btn-success" type="submit" name="Submit" id="reset-btn">
<div class="disclaimer"><p>By clicking submit you agree to receiving email alerts.</p></div>
</div>
</div>
</div>
</div>
</form>
**<div class = card>
Errors
{{safezone_form.errors.name}}
{{create_user_form.errors.email}}
{{create_user_form.errors.username}}
{{create_user_form.errors.password1}}
</div>**
Forms.py
password2 = None
email = forms.EmailField(widget=forms.EmailInput(attrs={"placeholder": "michael#gmail.com"}))
username = forms.CharField(widget=forms.TextInput(attrs={"placeholder": "JohnSmith078"}))
password1 = forms.CharField(widget=forms.PasswordInput(attrs={"placeholder": "8+ characters"}))
class Meta:
model = User
fields = ['username', 'email', 'password1']
def clean_password1(self):
password1 = self.cleaned_data.get('password1')
try:
password_validation.validate_password(password1, self.instance)
except forms.ValidationError as error:
self.add_error('password1', error)
return password1
class SafezoneForm(forms.ModelForm, admin.ModelAdmin):
name = forms.CharField(label='Safezone name',widget=forms.TextInput
(attrs={'id': 'name', 'label': 'Name of Safezone', 'class': 'form-inputs',"placeholder": "Mum's house"}))
latitudecentre = forms.FloatField(label='Safezone Latitude',widget=forms.TextInput
(attrs={'id': 'latitudecentre','class': 'form-inputs',"placeholder": "Latitude"}))
longitudecentre = forms.FloatField(label='Safezone Longitude',widget=forms.TextInput
(attrs={'id': 'longitudecentre','class': 'form-inputs',"placeholder": "Longitude"}))
class Meta:
model = Safezone
fields = ['name', 'longitudecentre', 'latitudecentre']
Your errors don't show because you're redirecting to another page if your forms are not valid.
if create_user_form.is_valid() and safezone_form.is_valid():
...
return redirect('safezoneaddedpage')
return redirect('safezoneaddedpage') # detelete this, here you must not redirect to another page, but render the same template.
and add this:
return render(request, 'V2maparonno_create_safe_zoneV2.html',
{'create_user_form': create_user_form, 'safezone_form': safezone_form})
I have my django app which searches youtube and return result as a dictionary which i render them in template, one of the returned value is link , now I have a download button they way i wish it to function is whenever you click a button it should take the url for the clicked result and pass it to another download function as an argument. How do I accomplish that ?
Here is my view.py
def index(request):
if request.method == 'POST':
query = request.POST['video_name']
n = 12
search = SearchVideos(str(query), offset = 1, mode = "json", max_results = n)
ytresults = search.result()
result_dict = json.loads(ytresults)
context = {
"result" : result_dict,
}
template_name = "youloader/results.html"
return render(request, template_name, context)
else:
query = "no copyright sound"
n = 12
search = SearchVideos(str(query), offset = 1, mode = "json", max_results = n)
index_results = search.result()
result_dict = json.loads(index_results)
context = {
"result" : result_dict
}
template_name = "youloader/index.html"
return render(request, template_name, context)
def downloading_video(request):
try:
with youtube_dl.YoutubeDL(video_opts) as ydl:
ydl.download(link)
except:
pass
here are my template.html
<div class="my-4" >
<div style="padding-top: 20px">
<div class="row" >
{% for result in result.search_result %}
<div class="col-12 col-sm-6 col-md-4 col-lg-4">
<div class="card shadow-sm border-0 my-2">
<img src="{{ result.thumbnails.1 }}" alt="{{ result.channelId }}">
<div class="card-body">
<h5 class="card-title">{{ result.link }}</h5>
<div class="d-flex flex-wrap justify-content-between card-subtitle my-2 text-muted small">
<a href="{{ result.link }}" class="text-secondary font-weight-bold">
<i class="fa fa-tablet mr-1"></i>{{ result.channel }}
</a>
<span><i class="fa fa-stopwatch mr-1"></i>{{ result.duration }}</span>
<span><i class="fa fa-eye mr-1"></i>{{ result.views }}</span>
<button type="button" class="btn btn-info dropdown-toggle" data-toggle="dropdown">Download</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#">Audio</a>
<a class="dropdown-item" href="#">Video</a>
</div>
<br>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
and here is the sample of the template rendered.
in the index function you can use redirect instead of render
index function:
def index(request):
if request.method == 'POST':
.
.
.
result_dict = json.loads(index_results)
link = result_dict.link
return redirect('youtubedl:download', link ) # first arg is your url route to downloading_video function like 'appname:urlname' and second is the link that coming from result_dic
else:
.
.
downloading_video function:
def downloading_video(request, link):
try:
with youtube_dl.YoutubeDL(video_opts) as ydl:
ydl.download(link)
except:
pass
this is the way i think you should use because your download function is in a separate template
I want to search for products in my app by their categories, retrieving data from firebase database. The search works but doesn't display the products and I can't figure out what other context is to be passed. I'm new to Django so any help would be appreciated.
here's my Welcome.html:
<form class="form-inline my-2 my-lg-0" method="get" action="/postsign" id="s">
{% csrf_token %}
<input class="form-control mr-sm-2" type="search" value="{{ category }}" placeholder="Search by category" aria-label="Search" name="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit" onclick="location.href='/postsign/?category={{ category }}'" form="s">Search</button>
</form>
</div>
</nav>
<div class="container">
<div class="col-md-4">
<div class="cards">
{% for product in category %}
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{{ product.image }}" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{ product.pname }}</h5>
<p class="price">{{ product.price }}</p>
<p class="card-text">{{ product.description }}</p>
<button class="btn btn-primary cart">Add to cart</button>
<button class="btn btn-primary" onclick="location.href='{% url 'productView' %}'">View product</button>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
Here's the views:
def postsign(request):
if request.method == 'GET' and 'csrfmiddlewaretoken' in request.GET:
search = request.GET.get('Search')
search = search.lower()
timestamps = database.child("Products").shallow().get().val()
pcategory = []
for i in timestamps:
category = database.child("Products").child(i).child("category").get().val()
category = str(category)+"$"+str(i)
pcategory.append(category)
matching =[str(string) for string in pcategory if search in string.lower()]
s_category = []
s_id = []
for i in matching:
category,ids=i.split("$")
s_category.append(category)
s_id.append(ids)
data = services.get_products()
return render(request, "Welcome.html",{'category':s_category})
Here's how my database looks:
products{
timestamp{
name:...
category:...
}
timestamp{
name:..
category:...
...
I am trying to edit multiple rows of data in a model via formsets. In my rendered form, I use javascript to delete (hide and assign DELETE) rows, and then save changes with post.
My view:
def procedure_template_modification_alt(request, cliniclabel, template_id):
msg = ''
clinicobj = Clinic.objects.get(label=cliniclabel)
template_id = int(template_id)
template= ProcedureTemplate.objects.get(templid = template_id)
formset = ProcedureModificationFormset(queryset=SectionHeading.objects.filter(template = template))
if request.method == 'POST':
print(request.POST.get)
# Create a formset instance with POST data.
formset = ProcedureModificationFormset(request.POST)
if formset.is_valid():
print("Form is valid")
instances = formset.save(commit=False)
print(f'instances:{instances}')
for instance in instances:
print(f'Instance: {instance}')
instance.template = template
instance.save()
msg = "Changes saved successfully."
print("Deleted forms:")
for form in formset.deleted_forms:
print(form.cleaned_data)
else:
print("Form is invalid")
print(formset.errors)
msg = "Your changes could not be saved as the data you entered is invalid!"
template= ProcedureTemplate.objects.get(templid = template_id)
headings = SectionHeading.objects.filter(template = template)
return render(request, 'procedures/create_procedure_formset_alt.html',
{
'template': template,
'formset': formset,
'headings': headings,
'msg': msg,
'rnd_num': randomnumber(),
})
My models:
class ProcedureTemplate(models.Model):
templid = models.AutoField(primary_key=True, unique=True)
title = models.CharField(max_length=200)
description = models.CharField(max_length=5000, default='', blank=True)
clinic = models.ForeignKey(Clinic, on_delete=models.CASCADE)
def __str__(self):
return f'{self.description}'
class SectionHeading(models.Model):
procid = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=200)
default = models.CharField(max_length=1000)
sortorder = models.IntegerField(default=1000)
fieldtype_choice = (
('heading1', 'Heading1'),
('heading2', 'Heading2'),
)
fieldtype = models.CharField(
choices=fieldtype_choice, max_length=100, default='heading1')
template = models.ForeignKey(ProcedureTemplate, on_delete=models.CASCADE, null=False)
def __str__(self):
return f'{self.name} [{self.procid}]'
My forms:
class ProcedureCrMetaForm(ModelForm):
class Meta:
model = SectionHeading
fields = [
'name',
'default',
'sortorder',
'fieldtype',
'procid'
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'class': 'form-control'})
self.fields['default'].widget.attrs.update({'class': 'form-control'})
self.fields['sortorder'].widget.attrs.update({'class': 'form-control'})
self.fields['fieldtype'].widget.attrs.update({'class': 'form-control'})
ProcedureCreationFormset = formset_factory(ProcedureCrMetaForm, extra=3)
ProcedureModificationFormset = modelformset_factory(SectionHeading, ProcedureCrMetaForm,
fields=('name', 'default', 'sortorder','fieldtype', 'procid'),
can_delete=True,
extra=0
# widgets={"name": Textarea()}
)
The template:
{% block content %} {% load widget_tweaks %}
<div class="container">
{% if user.is_authenticated %}
<div class="row my-1">
<div class="col-sm-2">Name</div>
<div class="col-sm-22">
<input type="text" name="procedurename" class="form-control" placeholder="Enter name of procedure (E.g. DNE)"
value="{{ template.title }}" />
</div>
</div>
<div class="row my-1">
<div class="col-sm-2">Description</div>
<div class="col-sm-22">
<input type="text" name="proceduredesc" class="form-control" placeholder="Enter description of procedure (E.g. Diagnostic Nasal Endoscopy)"
value="{{ template.description }}" />
</div>
</div>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %} {{ formset.management_form }}
<div class="row mt-3">
<div class="col-sm-1">Select</div>
<div class="col-sm-6">Heading</div>
<div class="col-sm-8">Default (Normal description)</div>
<div class="col-sm-2">Sort Order</div>
<div class="col-sm-4">Type</div>
<div class="col-sm-2">Action</div>
</div>
{% for form in formset %}
<div class="row procrow" id="row{{ forloop.counter0 }}">
<div class="" style="display: none;">{{ form.procid }}</div>
<div class="col-sm-6">
{{ form.name }}
</div>
<div class="col-sm-8">
<div class="input-group">
{{ form.default }}
</div>
</div>
<div class="col-sm-2">
<div class="input-group">
{{ form.sortorder }}
</div>
</div>
<div class="col-sm-4">
<div class="input-group">
{{ form.fieldtype }}
</div>
</div>
<div class="col-sm-2">
<div class="input-group">
<div class="input-group-append">
<button id="add{{ forloop.counter0 }}" class="btn btn-success add-row">+</button>
</div>
<div class="input-group-append">
<button id="del{{ forloop.counter0 }}" class="btn btn-danger del-row">-</button>
</div>
</div>
</div>
</div>
{% endfor %} {% endif %}
<div class="row my-3">
<div class="col-sm-8"></div>
<div class="col-sm-8">
<div class="input-group">
<div class="input-group-append mx-1">
<button id="save_report" type="submit" class="btn btn-success"><i class="fal fa-shield-check"></i>
Save Report Format</button>
</div>
<div class="input-group-append mx-1">
<button id="save_report" type="button" class="btn btn-danger"><i class="fal fa-times-hexagon"></i>
Cancel</button>
</div>
</div>
</div>
<div class="col-sm-8"></div>
</div>
<div>
{% for dict in formset.errors %} {% for error in dict.values %} {{ error }} {% endfor %} {% endfor %}
</div>
</form>
</div>
{% endblock %}
My data is displayed as below (Screenshot). I make changes with javascript when the delete button is pressed, so that the html becomes like this:
<div class="row procrow" id="row2" style="display: none;">
<div class="" style="display: none;"><input type="hidden" name="form-2-procid" value="25" id="id_form-2-procid"></div>
<div class="col-sm-6">
<input type="text" name="form-2-name" value="a" maxlength="200" class="form-control" id="id_form-2-name">
</div>
<div class="col-sm-8">
<div class="input-group">
<input type="text" name="form-2-default" value="v" maxlength="1000" class="form-control" id="id_form-2-default">
</div>
</div>
<div class="col-sm-2">
<div class="input-group">
<input type="number" name="form-2-sortorder" value="1000" class="form-control" id="id_form-2-sortorder">
</div>
</div>
<div class="col-sm-4">
<div class="input-group">
<select name="form-2-fieldtype" class="form-control" id="id_form-2-fieldtype">
<option value="heading1" selected="">Heading1</option>
<option value="heading2">Heading2</option>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="input-group">
<div class="input-group-append">
<button id="add2" class="btn btn-success add-row">+</button>
</div>
<div class="input-group-append">
<button id="del2" class="btn btn-danger del-row">-</button>
</div>
</div>
</div>
<input type="checkbox" name="form-2-DELETE" id="id_form-2-DELETE" checked=""></div>
On submitting the data, I get the following output, and data does not reflect the deletion I did. It displays the same thing again. There are no errors. But my edited data is not being saved.
Output:
<bound method MultiValueDict.get of <QueryDict: {'csrfmiddlewaretoken': ['ka3avICLigV6TaMBK5a8zeVJlizhtsKW5OTDBLlYorKd7Iji9zRxCX2vvjBv6xKu'], 'form-TOTAL_FORMS': ['3'], 'form-INITIAL_FORMS': ['3'], 'form-MIN_NUM_FORMS': ['0'], 'form-MAX_NUM_FORMS': ['1000'], 'form-0-procid': ['23'], 'form-0-name': ['External ear canal'], 'form-0-default': ['Bilateral external ear canals appear normal. No discharge.'], 'form-0-sortorder': ['100'], 'form-0-fieldtype': ['heading1'], 'form-1-procid': ['24'], 'form-1-name': ['Tympanic membrane'], 'form-1-default': ['Tympanic membrane appears normal. Mobility not assessed.'], 'form-1-sortorder': ['500'], 'form-1-fieldtype': ['heading1'], 'form-2-procid': ['25'], 'form-2-name': ['a'], 'form-2-default': ['v'], 'form-2-sortorder': ['1000'], 'form-2-fieldtype': ['heading1'], 'form-2-DELETE': ['on']}>>
Form is valid
instances:[]
Deleted forms:
{'name': 'a', 'default': 'v', 'sortorder': 1000, 'fieldtype': 'heading1', 'procid': <SectionHeading: a [25]>, 'DELETE': True}
You actually need to delete the instances: Loop through the formsets' deleted_objects property after you called saved(commit=False) and delete them.