How to get different names in request.post method - python

I got a problem, I'm making a web for SQLServer Agent Jobs execution, where if my job got parameters it redirects me to another page where I can enter my parameters. My problme is submiting these parameters. I don't know how to send all the parameters from my html to my view.py. All inputs have different names and I really don't know how to make the request accept different input names. I'll add some code below. IM commenting the line where I have the problem
parameters.html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %} Parametros {% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<div class="container">
<div class="row">
<div class="col-md-4 offset-md-4">
<br><br>
<div class="card">
<div class="card-header">
<h3>ParĂ¡metros</h3>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{% for i in parameters %}
<!-- Parameters input -->
<div class="form-outline mb-4">
<label class="form-label" for="form2Example1">{{ i.parameter_name }}</label>
{% if i.parameter_type == 'Int' %}
<input type="number" id="form2Example1" class="form-control" name="int" />
{% else %}
{% if i.parameter_type == 'Decimal' %}
<input type="text" id="form2Example1" class="form-control" name="decimal" />
{% else %}
{% if i.parameter_type == 'String' %}
<input type="text" id="form2Example1" class="form-control" name="string" />
{% else %}
{% if i.parameter_type == 'Date' %}
<input type="date" id="form2Example1" class="form-control" name="date" />
{% endif %}
{% endif %}
{% endif %}
{% endif %}
</div>
{% endfor %}
<!-- Submit button -->
<button type="submit" class="btn btn-primary btn-block mb-4">Ejecutar</button>
</form>
</div>
</div>
</div>
</div>
</div>
views.py
#job execution
def ejecutar(request, job_name):
cursor = connection.cursor()
job = Jobs.objects.get(job_name=job_name)
if job.flag_params == 0:
cursor.execute("EXEC msdb.dbo.sp_start_job '" + job.job_name + "'")
return HttpResponse("""<html><script>alert("Job ejecutado");window.location.replace('/home');</script></html>""")
else:
#redirects to parameters.html
redirect('parameters.html', job_name=job.job_name)
#get job parameters
parameters = Parametros.objects.filter(job_id=job.id)
if request.method == 'POST':
for parameter in parameters:
#update parameters
#Here I got the problem, in request.POST(), how can I get different input names from parameters.html (decimal, int, string, date)
cursor.execute("UPDATE Jobs_parametros SET parameter_value='" + request.POST['decimal'] + "' WHERE parameter_name='" + parameter.parameter_name + "' AND job_id='" + str(job.id) + "'")
cursor.execute("EXEC msdb.dbo.sp_start_job '" + job.job_name + "'")
return HttpResponse("""<html><script>alert("Job ejecutado");window.location.replace('/home');</script></html>""")
return render(request, 'parameters.html', {'parameters': parameters})
models.py
class Usuarios(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=100)
class Jobs(models.Model):
id = models.AutoField(primary_key=True)
job_name = models.CharField(max_length=100)
flag_activo = models.BooleanField(default=True)
flag_params = models.BooleanField(default=False)
class DetailJobUser(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(Usuarios, on_delete=models.CASCADE)
job = models.ForeignKey(Jobs, on_delete=models.CASCADE)
class Parametros(models.Model):
id = models.AutoField(primary_key=True)
job = models.ForeignKey(Jobs, on_delete=models.CASCADE)
parameter_name = models.CharField(max_length=100)
parameter_type = models.CharField(max_length=100)
parameter_value = models.CharField(max_length=100)
Thanks for your answers :D

Related

Flask: Use multiple instances of one form

My website lets a teacher create multiple questions for an assignment. Once the assignment is created, a student can come and write an answer for each question.
My problem is that only one answer is saved for each entry. For example, there are two questions in an assignment. The answer for question 1 is "asdf", the answer for question 2 is "fdsa". The content for both answers will be saved as "asdf", when they should be unique.
I have tried printing request.form and it looks like this (excluding the csrf_tokens):
('code_content', 'asdf'), ('code_content', 'fdsa'), ('submit', 'Submit Assignment')]
So I know that fdsa is still in there somewhere, but I'm not able to access it. If this is important, there were two csrf_tokens that were the exact same when printing request.form.
To get that data, I created a 'GetQuestionContent()' form for as many questions in the assignment. Like this:
questions = []
question_content_forms = []
for question in Question.query.all():
if int(question.owner) == int(assignment_id):
questions.append(question)
question_content_forms = [GetQuestionContent() for item in range(0, len(questions))]
Then, in the HTML, I write the form like this:
<form method="POST">
{% for question in questions %}
<div class="accordion-item">
<h2 class="accordion-header" id="heading{{ question.id }}">
<button class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapse{{ question.id }}"
aria-expanded="false"
aria-controls="collapse{{ question.id }}">
{{ question.title }}
</button>
</h2>
<div id="collapse{{ question.id }}"
class="accordion-collapse collapse"
aria-labelledby="heading{{ question.id }}"
data-bs-parent="#questionsAccordion">
<p>
<small>
<strong>Question Description</strong>
<br>
{% if question.description != "" %}
{{ question.description|safe }}
{% else %}
<em>The assignment creator did not provide a description for this question.</em>
{% endif %}
</small>
</p>
{{ question_content_forms[loop.index - 1].hidden_tag() }}
{% if question.type == "code" %}
<div class="code-box">
{{ question_content_forms[loop.index - 1].code_content(id = "editor") }}
</div>
{% endif %}
{% if question.type == "text" %}
{{ question_content_forms[loop.index - 1].text_content|safe }}
{% endif %}
</div>
</div>
{% endfor %}
{% if current_user.account_type == "Student" %}
{{ submit_button.submit(class="btn btn-outline-success mt-3", value="Submit Assignment")}}
{% endif %}
</form>
When the user presses submit, I want to get every answer and put it into their own entry for the StudentQuestionSubmission table in my database. This is what that code looks like:
if request.method == "POST" and submit_button.data:
print(request.form)
index = 0
for question in questions:
question_to_submit = StudentQuestionSubmission(question_id = int(question.id),
student_id = int(current_user.id))
if question.type == "code":
question_to_submit.question_content = question_content_forms[index].code_content.data
elif question.type == "text":
question_to_submit.question_content = question_content_forms[index].text_content.data
print(f"\n\n{ question_content_forms[index].code_content.data } \n \
{ question_content_forms[index].text_content.data } \n\n")
index += 1
db.session.add(question_to_submit)
assignment_to_submit = StudentAssignmentSubmission(assignment_id = int(assignment_id),
student_id = int(current_user.id),
has_submitted = True,
submission_date = date.today())
db.session.add(assignment_to_submit)
db.session.commit()
flash(f"'{assignment.name}' has been succesfully submitted.")
return redirect(url_for('classroom_assignments_list', class_id = class_id, paper_id = paper_id))
You can see that I print the data of the textboxes. It will output 'asdf' on both iterations even if I wrote something entirely different for question 2.
I appreciate any help. Thank you.
EDIT: 'hackily' getting the content from multiple instances of the same form using request.form.to_dict(flat=False)['your_form_field']
Here's the new code:
if request.method == "POST" and submit_button.data:
code_content = request.form.to_dict(flat=False)['code_content']
text_content = request.form.to_dict(flat=False)['text_content']
code_content_index = 0
text_content_index = 0
for question in questions:
question_to_submit = StudentQuestionSubmission(question_id = int(question.id),
student_id = int(current_user.id))
if question.type == "code":
question_to_submit.question_content = code_content[code_content_index]
code_content_index += 1
elif question.type == "text":
question_to_submit.question_content = text_content[text_content_index]
text_content_index += 1
print(f"\n\n{ question_to_submit.question_content } \n\n")
db.session.add(question_to_submit)
assignment_to_submit = StudentAssignmentSubmission(assignment_id = int(assignment_id),
student_id = int(current_user.id),
has_submitted = True,
submission_date = date.today())
db.session.add(assignment_to_submit)
db.session.commit()
flash(f"'{assignment.name}' has been succesfully submitted.")
return redirect(url_for('classroom_assignments_list', class_id = class_id, paper_id = paper_id))
My suggestion is not to create multiple forms, but to dynamically create one form for all the necessary questions.
In this case it is possible to assign a unique id to each field, which indicates that it belongs to the question.
The following example shows you a possible implementation.
An answer field is added to the form for each question, which has the id of the question in its name. Thus, the respective question can be assigned when rendering and querying the input data.
Flask
from flask import (
Flask,
render_template,
request
)
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import TextAreaField, SubmitField
from wtforms.validators import DataRequired
import random
app = Flask(__name__)
app.secret_key = 'your secret here'
db = SQLAlchemy(app)
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
type = db.Column(db.String)
owner = db.Column(db.Integer)
title = db.Column(db.String)
description = db.Column(db.Text)
with app.app_context():
db.drop_all()
db.create_all()
qs = [Question(
type=random.choice(['code', 'text']),
owner=1,
title=f'Question {i+1}',
description=f'Your description here.'
) for i in range(3)]
db.session.add_all(qs)
db.session.commit()
def form_factory(qs):
class F(FlaskForm):
submit = SubmitField('Submit')
for q in qs:
field = TextAreaField(
q.type.title(),
validators=[
# DataRequired()
],
)
setattr(F, f'q-{q.id}', field)
return F
#app.route('/', methods=['GET', 'POST'])
def index():
questions = Question.query.filter_by(owner=1).all()
form = form_factory(questions)(request.form)
if form.validate_on_submit():
for q in questions:
field = getattr(form, f'q-{q.id}')
print(f'Question-{q.id}\n{field.data}\n')
return render_template('index.html', **locals())
HTML (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Index</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
<div class="container my-3">
<form method="post">
{{ form.hidden_tag() }}
<div class="accordion mb-3" id="accordionExample">
{% for q in questions -%}
<div class="accordion-item">
<h2 class="accordion-header" id="heading-{{loop.index}}">
<button
class="accordion-button collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapse-{{loop.index}}"
aria-expanded="false"
aria-controls="collapse-{{loop.index}}"
>
{{ q.title }}
</button>
</h2>
<div
id="collapse-{{loop.index}}"
class="accordion-collapse collapse"
aria-labelledby="heading-{{loop.index}}"
data-bs-parent="#accordionExample"
>
<div class="accordion-body">
<div class="mb-3">
{{ q.description|safe }}
</div>
{% set field = form|attr('q-{}'.format(q.id)) -%}
<div>
{{ field.label(class_='form-label') }}
{{ field(class_='form-control' + ('', ' editor')[q.type=='code']) }}
</div>
</div>
</div>
</div>
{% endfor -%}
</div>
<div class="d-grid gap-2">
{{ form.submit(class_='btn btn-primary') }}
</div>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
</body>
</html>

Dango - show title from multiple models in autocomplete search bar

I want to display titles from 2 models in my autocomplete feature in the search bar, however, I am not sure how to write a loop in search_address_qa function that would display titles from multiple models.
For now, I can only properly display address_objects (Article) or address_objects_qa(QA) but not both. The results from search_items are fine. When I try to put for address_object in address_objects_qa or address_objects then I get some random results.
models.py
class QA(models.Model):
title=models.CharField(max_length=1000, help_text='max 1000 characters')
body = RichTextField(verbose_name='Description', blank=True)
class Article(models.Model):
title=models.CharField(max_length=1000, help_text='max 1000 characters')
body = RichTextField(verbose_name='Description', blank=True)
views.py
#login_required
def search_address_qa(request):
query = request.GET.get('title')
payload = []
if query:
lookups = Q(title__icontains=query)
address_objects = Article.objects.filter(lookups, status=1)
address_objects_qa = QA.objects.filter(lookups, status=1)
for address_object in address_objects_qa:
payload.append(address_object.title)
return JsonResponse({'status':200, 'data': payload})
#login_required
def search_items(request):
query = request.GET.get('q')
article = Article.objects.filter(title__icontains=query)
qa_list = QA.objects.filter(title__icontains=query)
if query is not None:
lookups = Q(title__icontains=query) |Q(body__icontains=query)
article = Article.objects.filter(lookups).distinct()
qa_list = QA.objects.filter(lookups).distinct()
context = {
'query_name': query,
'search_items': article,
'qa_list': qa_list,
}
return render(request, 'search/search_items.html', context)
search_items.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/#trevoreyre/autocomplete-js/dist/style.css" />
</head>
<body>
<main class="container-fluid">
<!--HEADER-->
<header class="header" id="header">
<h3 class="col-6">Search results for: {{ query_name }}</h3>
<!--SEARCH BAR-->
<button class="col-6" onclick="openSearch()"><i class="fas fa-search fa-sm"></i></button>
<form action="{% url 'search_items' %}" method="get" id="search">
{% csrf_token %}
<div class="searchbar" id="autocomplete">
<input name="q" type="text" placeholder="Search..." class="search_input">
<button class="search_icon"><i class="fas fa-search fa-sm"></i></button>
<ul class="autocomplete-result-list"></ul>
</div>
</form>
<!--END SEARCH BAR-->
</header>
<!--END HEADER-->
{% if qa_list %}
<section class="py-3">
<h2>Q&A's</h2>
<hr>
<div class="row">
{% for qa in qa_list %}
<div class="col-10">
{{qa.title}}
</div>
{% endfor %}
</div>
</section>
{% endif %}
{% if search_items %}
<section class="py-3">
<h2>Q&A's</h2>
<hr>
<div class="row">
{% for article in search_items %}
<div class="col-10">
{{article.title}}
</div>
{% endfor %}
</div>
</section>
{% endif %}
</main>
<!--JS files-->
<script src="https://unpkg.com/#trevoreyre/autocomplete-js"></script>
As suggested in comments I used itertools.chain to iterate over 2 models. I am posting the code below. Maybe it will be useful for someone.
from itertools import chain
#login_required
def search_title(request):
query = request.GET.get('title')
payload = []
if query:
lookups = Q(title__icontains=query)
optimazon_titles = Article.objects.filter(lookups, status=1)
qa_titles = QA.objects.filter(lookups, status=1)
payload = map(lambda x: x.title, chain(optimazon_titles, qa_titles))
return JsonResponse({'status':200, 'data': list(payload)})

Form wont validate, says that all fields are empty Django

In a view I have 3 forms:
forms.py
class PostForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(PostForm, self).__init__(*args, **kwargs)
class Meta:
model = Post
fields = ['subtitle', 'latitude', 'longitude', 'tags', 'body']
widgets = {
'body': forms.Textarea(attrs={'class': 'log-body editable'}),
'tags': forms.TextInput(attrs={'id': 'tags-field', 'class': 'log-form-field'}),
'latitude': forms.TextInput(attrs={'id': 'latitude-field', 'class': 'log-form-field'}),
'longitude': forms.TextInput(attrs={'id': 'longitude-field', 'class': 'log-form-field'}),
'subtitle': forms.TextInput(attrs={'id': 'subtitle-field', 'class': 'log-form-field'}),
}
labels = {
'subtitle': 'Subtitle:',
'tags': 'Tags:',
'latitude': 'Latitude',
'longitude': 'Longitude',
'body': ''
}
class ImageForm(forms.ModelForm):
images = forms.ImageField(label='Images', widget=forms.ClearableFileInput(
attrs={
'multiple': True,
'class': 'file-upload',
'id': 'file-upload-button-image',
'name': 'images'}
)
)
class Meta:
model = PostImage
fields = ('images',)
class VideoForm(forms.ModelForm):
videos = forms.FileField(label='Videos', widget=forms.ClearableFileInput(
attrs={
'multiple': True,
'class': 'file-upload',
'id': 'file-upload-button-video',
'name': 'images'
}
)
)
class Meta:
model = PostVideo
fields = ('videos',)
And I have a template that creates a post and stores the videos and pictures and that works great. Where I'm having a hard time is updating a 'Post'.
class PostEditView(TemplateView):
template_name = 'Logging/edit view.html'
post_form_class = PostForm
image_form_class = ImageForm
video_form_class = VideoForm
def get_context_data(self, **kwargs):
context = super(PostEditView, self).get_context_data(**kwargs)
context['post_pk'] = self.kwargs['pk']
context['post_form'] = PostForm(instance=Post.objects.get(pk=self.kwargs['pk']))
context['image_form'] = ImageForm(empty_permitted=True, use_required_attribute=False)
context['video_form'] = VideoForm(empty_permitted=True, use_required_attribute=False)
context['images'] = PostImage.objects.filter(post_id=self.kwargs['pk'])
context['videos'] = PostVideo.objects.filter(post_id=self.kwargs['pk'])
return context
def post(self, request, *args, **kwargs):
context = self.get_context_data()
post_data = request.POST or None
if post_data.get('Delete'):
if len(post_data.getlist('img-index[]')) > 0:
for i in post_data.getlist('img-index[]'):
PostImage.objects.filter(id=i).delete()
if len(post_data.getlist('vid-index[]')) > 0:
for i in post_data.getlist('vid-index[]'):
PostVideo.objects.filter(id=i).delete()
print(post_data)
post_form = PostForm(data=post_data, instance=Post.objects.get(pk=self.kwargs['pk']), prefix='post')
print(post_form.is_bound)
post_form.is_valid()
print(post_form.errors)
images = request.FILES.getlist('image-images')
videos = request.FILES.getlist('video-videos')
if post_form.is_valid():
print('valid form')
for i in images:
instance = PostImage(image=i, post=context['post_pk'])
instance.save()
for v in videos:
instance = PostVideo(video=v, post=context['post_pk'])
instance.save()
return super(PostEditView, self).render_to_response(context)
def form_save(self, form, request):
obj = form.save(commit=False)
obj.user = request.user
obj.author = request.user.first_name + ' ' + request.user.last_name
obj.event_type = 'Log Entry'
obj.save()
messages.success(self.request, "{} posted successfully".format(obj))
return obj
When I call is_valid() on post_form it always says false, although it does say its bound. My post object does contain the data from the form in my template, including a csrf token, but for some reason the form is never valid and says that all the fields are empty.
from print(post_data):
<QueryDict: {'csrfmiddlewaretoken': ['h5uxuACKsvBcO4lrPB7yKbYgr0BsASEklT3GTp6R3t8na13TadAfjbihl2VyGvdC'], 'subtitle': ['Test with photos'], 'latitude': ['48.000'], 'longitude': ['112.000'], 'tags': ['[]'], 'images': [''], 'videos': [''], 'body': ['<p>body test 2 saa</p>']}>
from print(post_form.is_bound):
True
from print(post_form.errors):
<ul class="errorlist">
<li>subtitle<ul class="errorlist"><li>This field is required.</li></ul></li><li>latitude
<ul class="errorlist"><li>This field is required.</li></ul></li><li>longitude
<ul class="errorlist"><li>This field is required.</li></ul></li><li>tags
<ul class="errorlist"><li>This field is required.</li
></ul></li><li>body
<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
Models.py
class Post(models.Model):
class Status(models.TextChoices):
active = 'Active'
inactive = 'Inactive'
user = models.ForeignKey(Account, on_delete=models.CASCADE)
author = models.CharField(max_length=255)
title = models.CharField(max_length=80, default='Log Entry: ' + datetime.datetime.now().strftime("%m/%d/%Y, %H:%M:%S"))
subtitle = models.CharField(max_length=255)
latitude = models.DecimalField(decimal_places=3, max_digits=6)
longitude = models.DecimalField(decimal_places=3, max_digits=6)
post_time = models.DateTimeField(auto_now_add=True)
tags = TaggableManager()
body = models.TextField()
history = HistoricalRecords()
event_type = models.CharField(max_length=50, choices=EventType.choices, default='Log Entry', editable=False)
status = models.CharField(max_length=10, choices=Status.choices, default='Active')
def __str__(self):
return 'Post by: ' + str(self.user) + " on: " + self.post_time.strftime("%m/%d/%Y at %H:%M:%S")
def get_image_filename(instance, filename):
title = instance.post.title
slug = slugify(title)
return "post_media/%s/%s" % (slug, filename)
class PostImage(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.PROTECT)
image = models.ImageField(upload_to=get_image_filename, verbose_name='Image')
def filename(self):
return self.image.name.split('/')[-1]
class PostVideo(models.Model):
post = models.ForeignKey(Post, default=None, on_delete=models.PROTECT)
video = models.FileField(upload_to=get_image_filename, verbose_name='Video')
def filename(self):
return self.video.name.split('/')[-1]
template:
{% extends 'layout/base.html' %}
{% load static %}
{% block titleblock %}New Log{% endblock %}
{% block header %}
<script src="{% static 'Logging/js/medium-editor.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'Logging/css/medium-editor.min.css' %}">
<link rel="stylesheet" href="{% static 'Logging/css/new_post.css' %}">
{% endblock %}
{% block bodyblock %}
<form class="post-form" id="post-form" enctype="multipart/form-data" method="POST" action=".">
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="Modal-title" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Confirm</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">Ă—</span>
</button>
</div>
<div class="modal-body">
Are you sure you want to delete these items?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-danger" name="Delete" value="1" form="post-form">Delete</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-10 col-sm-12">
{% csrf_token %}
{% for field in post_form %}
{% ifnotequal field.label '' %}
<div class="input">
{{ field.label_tag }}
{{ field }}
</div>
<br>
{% endifnotequal %}
{% endfor %}
</div>
<div class="col-lg-2 col-sm-12 button-col">
<label for="file-upload-button-image" class="custom-file-upload">
<div class="upload-button-wrapper">
{{ image_form.images }}
<p id="image-num"></p>
<img src="{% static 'layout/img/image.svg' %}" alt="svg" id="img-svg">
<img src="{% static 'layout/img/plus-circle.svg' %}" alt="svg+" id="plus-svg">
</div></label>
<label for="file-upload-button-video" class="custom-file-upload">
<div class="upload-button-wrapper">
{{ video_form.videos }}
<p id="video-num"></p>
<img src="{% static 'layout/img/film.svg' %}" alt="svg" id="img-svg">
<img src="{% static 'layout/img/plus-circle.svg' %}" alt="svg+" id="plus-svg">
</div></label>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-12 edit-col">
<div class="images_existing">
{% for image in images %}
<div class="stacker">
<div class="image-selector-wrapper">
<input type="checkbox" id="" name="img-index[]" class="invisible img-checkboxes" value="{{ image.pk }}">
<img class="thumbnail" src="{{ image.image.url }}" alt="{{ image.filename }}">
<h6>{{ image.filename }}</h6>
{% if forloop.first %}
<div class="num-indicator" id="image-number"></div>
{% endif %}
</div>
</div>
{% endfor %}
<div class="button-box">
<button type="submit" name="download" value="1" class="btn-primary">Download</button>
<button type="button" class="btn-danger" data-toggle="modal" data-target="#deleteModal">Delete</button>
</div>
</div><div class="edit" id="edit-images">Edit</div>
</div>
<div class="col-lg-4 col-md-6 col-sm-12 edit-col">
<div class="videos_existing">
{% for video in videos %}
<div class="stacker">
<div class="video-selector-wrapper">
<input type="checkbox" id="" name="vid-index[]" value="{{ video.pk }}" class="invisible video-cb">
<img class="thumbnail-video" src="{% static 'layout/img/film.svg' %}" alt="{{ video.filename }}">
<h6>{{ video.filename }}</h6>
{% if forloop.first %}
<div class="num-indicator" id="video-number"></div>
{% endif %}
</div></div>
{% endfor %}
</div><div class="edit" id="edit-video">Edit</div>
</div></div>
<div class="row">
<div class="col">
{{ post_form.body }}
<button type="submit" class="custom-submit-button"><img src="{% static 'layout/img/upload.svg' %}" alt="submit"> <span>Submit</span></button>
</div>
</div>
{% if post_form.errors %}
{% for field in post_form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in post_form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
</form>
<script>var editor = new MediumEditor('.editable');</script>
<script src="{% static 'Logging/js/new_post.js' %}"></script>
{% endblock %}
I can not for the life of my figure this out. Any help would be appreciated!

How to delete an item that is connected to a foreignkey django?

I have a problem adding a delete functionality to my simple django project which is a todoapp. The problem is when i press the delete button it redirect me to the same page but the item is not deleted. Can someone explain to me what is happening on my code?
This is my code solution but still does not work.
This is my views.py
def index(request, id):
ls = ToDoList.objects.get(id=id)
p = request.POST
if request.method == "POST":
if p.get("save"):
for item in ls.item_set.all():
item_id = str(item.id)
if "clicked" == p.get("c" + item_id):
item.complete = True
else:
item.complete = False
if p.get("text" + item_id) in p:
item.text = p.get("text" + item_id)
if p.get("d" + item_id) == "delete": # Solution
item.delete()
return HttpResponseRedirect("/%i" % ls.id)
item.save()
elif p.get("add"):
new_item = p.get("new")
if new_item:
ls.item_set.create(text=new_item)
else:
return HttpResponse("<strong>Invalid Input</strong>")
return render(request, "todoapp/index.html", {"ls": ls})
models.py
from django.db import models
class ToDoList(models.Model):
date = models.DateTimeField(auto_now_add=True)
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Item(models.Model):
toDoList = models.ForeignKey(ToDoList, on_delete=models.CASCADE)
text = models.CharField(max_length=500)
complete = models.BooleanField(default=False)
def __str__(self):
return self.text
index.html
{% extends 'todoapp/base.html' %}
{% block title %}View List{% endblock %}
{% block content %}
<h2>{{ls.name}}</h2>
<form method="post", action="#">
{% csrf_token %}
{% for item in ls.item_set.all%}
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-text">
<input class="btn btn-danger btn-sm" type="submit" name="d{{item.id}}" value="delete"> <!-- Solution -->
<input type="checkbox" name="c{{item.id}}" value="clicked" aria-label="Checkbox for following text input" {% if item.complete %} checked {% endif %}>
</div>
</div>
<input type="text" name="text{{item.id}}" value="{{item.text}}" class="form-control" aria-label="Text input with checkbox">
</div>
{% endfor %}
<div class="input-group mb-3">
<div class="input-group-prepend">
<button name="add", value="add", type="submit", class="btn btn-success">Add New</button>
</div>
<input type="text" name="new" value="" class="form-control">
</div>
<br>
<button name="save", value="save", type="submit", class="btn btn-success">Save</button>
</form>
{% endblock %}
I think it should work if you include the delete logic inside another 'if' clause.
if p.get("delete"):
for item in ls.item_set.all():
item_id = str(item.id)
if p.get("d" + item_id) == "delete": # Solution
item.delete()
return HttpResponseRedirect("/%i" % ls.id)
However, I'm not sure what you are trying to achieve as the end result. Here, only one item would get deleted (the item for which 'delete' button was clicked).

Attribute error : 'WSGIRequest' object has no attribute 'get'

I've been working on a project lately and got the above error. It says " Error during template rendering".I have a similar model, which works perfectly fine. I've looked for similar errors but got none matching my situation. I don't know where I went wrong. It would be great if I get helpful answers.
Models.py
class ServiceTax(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,related_name="service_tax",null=True,blank=True)
name=models.CharField(max_length=100)
percent=models.FloatField(default='0')
add_amount=models.IntegerField(default='0')
def __str__(self):
return self.name
Forms.py
class ServiceTaxForm(forms.ModelForm):
class Meta:
model = ServiceTax
fields = "__all__"
widgets = {
'name' : forms.TextInput(attrs={'class': 'form-control'}),
'percent' : forms.NumberInput(attrs={'class': 'form-control','step':'0.01'}),
'add_amount' : forms.NumberInput(attrs={'class':'form-control','maxlength':5}),
}
labels={
'add_amount': "Additional Amount"
}
Views.py
def tax_form(request,id=0):
if request.method == 'GET':
if id == 0:
form = ServiceTaxForm(request)
else:
tax = ServiceTax.objects.get(pk=id)
if tax in request.user.service_tax.all():
form = ServiceTaxForm(request,instance=tax)
else:
return redirect('/revenue/tax')
return render(request,'tax-form.html',{'form':form})
else:
if id==0:
form = ServiceTaxForm(request,request.POST)
if form.is_valid():
name = form.cleaned_data["name"]
percent = form.cleaned_data["percent"]
add_amount = form.cleaned_data["add_amount"]
t = AnnualTax(
name=name,
percent=percent,
add_amount=add_amount,
)
t.save()
request.user.service_tax.add(t)
else:
tax = ServiceTax.objects.get(pk=id)
if tax in request.user.service_tax.all():
form = ServiceTaxForm(request,request.POST,instance=tax)
if form.is_valid():
name = form.cleaned_data["name"]
percent = form.cleaned_data["percent"]
add_amount = form.cleaned_data["add_amount"]
tax_obj = ServiceTax.objects.get(pk=id)
tax_obj.name = name
tax_obj.percent = percent
tax_obj.add_amount = add_amount
tax_obj.save()
return redirect('/revenue/tax')
tax-form.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<i class="fa fa-chevron-circle-left fa-3x m-2"></i>
<div class="content">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">Add Service Tax</h4>
</div>
<div class="card-body">
<form action="" method="POST" autocomplete="off">
{% csrf_token %}
<div class="row">
<div class="col-md-4 pr-1">
<div class="form-group">
{{ form.name | as_crispy_field}}
</div>
</div>
<div class="col-md-4 pr-1">
<div class="form-group">
{{ form.percent | as_crispy_field}}
</div>
</div>
<div class="col-md-4 pr-1">
<div class="form-group">
{{ form.add_amount | as_crispy_field}}
</div>
</div>
</div>
<button type="submit" class="btn btn-success btn-fill pull-right">
{% if request.get_full_path == '/income/tax/add/' %}
Add Tax
{% else %}
Update
{% endif %}
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
You should retrieve your forms passing request.METHOD, not just request
As an example this piece of code form = ServiceTaxForm(request) should be form = ServiceTaxForm(request.POST)

Categories