I have items where I can easily edit one by one all working nice but in case I want to edit multiple id's at once via selecting with checkbox I am stuck and can't get it work. Where am I doing wrong ?
Here is my codes:
fast_edit.html -> I am passing variables via instance to field.
<div class="row">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-body">
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
{%csrf_token%}
{%for field in instance %}
<table class="table">
<tbody>
<tr>
<td width="100">
{{field.label_tag}}
</td>
<td>
{{field}}
</td>
</tr>
</tbody>
</table>
{% endfor %}
<div class="form-group">
<div class="col-sm-offset-6 col-sm6">
<button type="submit" class="btn btn-primary">Update FP Item</button>
</div>
</form>
</div>
</div>
</div>
</div>
forms.py
class FastFPForm(forms.ModelForm):
class Meta:
model = FP
fields = ['FP_Item', 'P_1', 'P_2']
widgets = {
'FP_Item': Textarea(attrs={'cols': 50, 'rows': 3}),
'P_1': Textarea(attrs={'cols': 50, 'rows': 1}),
'P_2': Textarea(attrs={'cols': 50, 'rows': 1}),
}
view.py --> I am sending variables to fast_edit function
def items_home(request):
pfast_type = request.GET.get("pfast_type")
item = request.GET.get("fastedit")
........
elif pfast_type and item:
return fast_edit(pfast_type,item)
Here is my function:
def fast_edit(request,id=None):
if not request.user.is_active:
return render(request, 'login.html')
else:
instance=get_object_or_404(FP,id=item)
form = FastFPForm(request.POST or None,instance=instance)
if form.is_valid():
instance = form.save(commit=False)
instance.user_id = request.user.id
instance.save()
return HttpResponseRedirect(instance.get_absolute_url())
context={
'FP' : FP.FP_Item,
'instance': instance,
'form': form
}
return render(request, 'fast_edit.html', context)
This is my inputs for fastedit and pfast_type to get the id's and the type.
<input type="checkbox" id="P_1" name="pfast_type" value="P_1"/>
<input type="checkbox" id="{{ obj.id }}" name="fastedit" value="{{ obj.id }}"/>
I know that my function is not correct but I couldn't fix it according to my need, so what I want to do is if P_1 checked, I want all selected items editable for P_1 field, if I select P_2 again all selected items editable for me to be able to save on fast_edit page.
Is my logic false ? Is there any other easier method for editing multiple id at once via selecting with checkbox or if I am on the right track can you please give me hint to solve this. Thank you
I added but I don't think I need url right as like as we are editing single id like url(r'^detail/(?P\d+)/$',
urls.py
url(r'^fast_edit/$', views.fast_edit, name='fast_edit'),
Related
I have a problem using Django forms while learning Django and adapting code from a variety of online courses and examples. As a result, the code may be “messy” – but if I can get it to work the way I need, I can improve my coding style later.
I wish to display a template that contains a form. Some of the data displayed in the page rendered in the template is read from one table/model, polls_CC_Questions, and I wish to write data input in the page into a related table, polls_CC_Resp_NoFK.
The models used are:
class CC_Questions(models.Model):
q_text = models.CharField('Question text', max_length=200)
C1_Type = models.CharField('Choice 1 Type', max_length=2)
Choice1_text = models.CharField('Choice 1 text', max_length=100)
C2_Type = models.CharField('Choice 2 Type', max_length=2)
Choice2_text = models.CharField('Choice 2 text', max_length=100)
#
def __str__(self):
return self.q_text[:20]
class CC_Resp_NoFK(models.Model):
Person_ID = models.IntegerField()
Test_date = models.DateTimeField('date test taken')
Q_ID = models.IntegerField()
Response_value = models.IntegerField(default=0,
validators=[MaxValueValidator(100), MinValueValidator(-100)])
#
def __str__(self):
return self.Person_ID
Now I can display the template containing valid data when I enter the url:
http://localhost:8000/polls/p2vote/4/
This is processed in urls.py
app_name = 'polls'
urlpatterns = [
…..
……
# ex: /polls/p2vote/<q_id>
path('p2vote/<int:q_id>/', p2_views.p2vote, name='p2vote'),
…..
The views.py entry that is used:
def p2vote(request,q_id):
#next line has been copied from CC_quest view to GET Question data
CC_question = get_object_or_404(CC_Questions, pk=q_id)
#
if request.method == 'POST':
form = VoteForm(request.POST)
if form.is_valid():
form.save()
return redirect('/polls/p2')
else:
formV = VoteForm()
#context = {'form' : formV}
return render(request, 'pollapp2/vote.html', {'var_name':CC_question,'form' : VoteForm()})
in forms.py
class VoteForm(forms.ModelForm):
class Meta:
model = CC_Resp_NoFK
fields = ['Person_ID', 'Test_date', 'Q_ID','Response_value']
The template launched, uses data from the polls_CC_Questions model/table to create the labels of the input field. This works fine so my displayed page
http://localhost:8000/polls/p2vote/5/
Displays data from the CC_Questions table, “carried in the variable varname” what the questions and their choices are. For example, the template displays the contents of {{ var_name.q_text }} and {{ var_name.Choice1_text }} , see below
Also, the page displayed containing the ModelForm is correctly displayed with labels. The template used :
<!-- vote.html based on create.html -->
<!-- 2022-02-17
Change text on page
Extracted data from CC_Question record passed as varname
-->
{% extends "pollapp2/base.html" %}
<!-- load widget tools to give me more control over layout of form in template -->
{% load widget_tweaks %}
<!-- block Title is the name in the tab -->
{% block title %}Vote on Question{% endblock %}
{% block main %}
<div class="row">
<div class="col-lg-10 col-lg-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Select one from two choices</h3>
</div>
<form method="POST">
{% csrf_token %}
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label for="question">Question to answer</label>
{{ var_name.q_text }}
</div>
</div>
</div>
<div class="row">
<div class="col-lg-5">
<div class="form-group">
<label for="Choice1_text ">Choice 1</label>
{{ var_name.Choice1_text }}
</div>
</div>
<div class="col-lg-5">
<div class="form-group">
<label for="option2">Choice 2</label>
{{ var_name.Choice2_text }}
</div>
</div>
</div>
<!-- Attempt at Input fields follow -->
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label for="Person_id">Person ID</label>
{% render_field form.Person_ID rows="1" class="form-control" %}<br>
<label for="Test_date">Test Date</label>
{% render_field form.Test_date rows="1" class="form-control" %}<br>
<label for="Q_ID">Question ID</label>
{% render_field form.Q_ID rows="1" class="form-control" %} <br>
<label for="Response_value">Response value</label>
{% render_field form.Response_value rows="1" class="form-control" %}
</div>
</div>
</div>
<div class="row">
<hr />
<div class="col-lg-4">
<button type="submit" class="btn btn-info">Submit</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
To summarise. All the above “works” in the sense a page is displayed when url : http://localhost:8000/polls/p2vote/X/ is entered in the browser and “X” is the id of the question , extracting data from the model: CC_questions. Also, on the page are input boxes created by the form, VoteForm, that allow data to be entered into table/model CC_Resp_noFK.
However, what I want to do is NOT offer Q_ID as an input field in the page, but instead populate it with the value from variable {{ var_name.id }}. I can’t work out whether I need to modify the vote.html template in some way, particularly the line:
<label for="Q_ID">Question ID</label>
{% render_field form.Q_ID rows="1" class="form-control" %} << change this ??
or the view, somewhere around form.save() ??
def p2vote(request,q_id):
#next line has been copied from CC_quest view to get Question data
CC_question = get_object_or_404(CC_Questions, pk=q_id)
#
if request.method == 'POST':
form = VoteForm(request.POST)
if form.is_valid():
form.save() << Somewhere around here ??
return redirect('/polls/p2')
else:
formV = VoteForm()
#context = {'form' : formV}
# return render(request, 'pollapp2/vote.html', context)
# following return tries to send question record into vote.html template
return render(request, 'pollapp2/vote.html', {'var_name':CC_question,'form' : VoteForm()})
Step 1: Delete Q_ID from VoteForm.
class VoteForm(forms.ModelForm):
class Meta:
model = CC_Resp_NoFK
fields = ['Person_ID', 'Test_date', 'Response_value']
Step 2: Add Q_ID after check if the form is valid and before save the object.
def p2vote(request,q_id):
#next line has been copied from CC_quest view to get Question data
CC_question = get_object_or_404(CC_Questions, pk=q_id)
if request.method == 'POST':
form = VoteForm(request.POST)
if form.is_valid():
item = form.save(commit=False)
item.Q_ID = q_id
item.save()
return redirect('/polls/p2')
My goal is to update the view using ajax. when the user enters a value in those 3 fields and save those fields to the database with for this user.
I have a user model with 3 text field as follow
class Q3Sign(models.Model):
title = models.CharField(max_length =255,blank =True)
title2 = models.CharField(max_length =255, blank = True)
title3 = models.CharField(max_length =255,blank =True)
user = models.ForeignKey(User, on_delete=models.CASCADE )
class Meta:
db_table = "Q3sign"
and my view is as fellow, I am getting the following error when I try to populate the fields.
django.db.utils.IntegrityError: NOT NULL constraint failed: Q3sign.user_id
class Createcourse(generic.CreateView):
model = Q3Sign
fields = ['title','title2','title3']
template_name = 'Q3canA/create_course.html'
success_url = reverse_lazy('create_course')
def create_course(self, request):
members = Q3Sign.objects.all()
return render (request,'Q3canA/create_course.html' , {'members':members})
def insert(request):
member = Q3Sign(title=request.POST['title'], title2=request.POST['title2'],
title3=request.POST['title3'], user=request.POST['user.id'])
member.save()
return redirect('create_course')
and here is my html
<div class="container">
<h2>Courses</h2>
<form method=post>
{% csrf_token %}
{{ form.as_p}}
<input type="submit" value="Create course" />
</form>
</div>
<form method="post">
{% csrf_token %}
<div class="form-inline">
<label>Course 1</label>
<input type="text" id="title" name="title" class="form-control"/>
</div>
<br />
<div class="form-inline">
<label>Course 2</label>
<input type="text" id="title2" name="title2" class="form-control"/>
<label>Course 3</label>
<input type="text" id="title3" name="title3" class="form-control"/>
</div>
<br />
<div class="col-md-4"></div>
<div class="col-md-4 form-group">
<button type="button" class="btn btn-primary form-control" id="submit">Submit</button>
</div>
</form>
<hr style="border-top:1px solid #000; clear: both;" />
<table class"table table-bordered">
<thead class = "alert-warning">
<tr>
<th>Course 1</th>
<th>Course 2</th>
<th>Course 3</th>
</tr>
</thead>
<tbody>
{% for member in members %}
<tr>
<td></td>
<td>{{member.user.id}}</td>
<td>{{member.title}}</td>
<td>{{member.title2}}</td>
<td>{{member.title3}}</td>
</tr>
{% endfor%}
</tbody>
</table>
{% endblock %}
Update now the fields disappeared :
Here is my URLs
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.home, name='home'),
#Auth
path('signup', views.Signup.as_view(), name = 'signup'),
path('login', auth_view.LoginView.as_view(), name = 'login'),
path('logout', auth_view.LogoutView.as_view(), name = 'logout'),
#Q3Course
path('createcourse',views.Createcourse.as_view(), name = 'create_course'),
url(r'^create_course', views.Createcourse.createcourse, name='create_course'),
]
urlpatterns += static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)
thanks to #Fifon the code now working.
The only issue I need to understand is why the if statement is not working.
if the fields are empty or if it contains a test it still saves it in the database and not raising the alert in the if clause?
$(document).ready(function(){
$('#submit').on('click', function(){
$title = $('#title').val();
$title2 = $('#title2').val();
$title3 = $('#title3').val();
$user = $('#user').val();
if($title.toLowerCase().indexOf('test') == -1 || $title2 == "" || $title3 == "" || $user = ""){
alert("Please complete field");
}else{
$.ajax({
type: "POST",
url: "/create_course",
data:{
title: $title,
title2: $title2,
title3: $title3,
user: $user,
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function(){
alert('Save Data');
$('#title').val('');
$('#title2').val('');
$('#title3').val('');
$('#user').val('');
window.location = "/create_course";
}
});
}
});
});
Firstly, there is no need for your insert() method. As you have a CreateView, you should use this, which will handle creating your objects and inserting them into the database. You should make use of the form this CreateView provides for you, rather than manually creating HTML for the form. This will make your life easier and ensure proper validation takes place. Something like this:
<form method="POST" id="create-course-form">
{% csrf_token %}
{{ form.as_p}}
<input type="submit" value="Create course" />
</form>
Your HTML is a little bit confusing right now – there is a form rendered using the {{ form.as_p }} template tag, and a manually rendered form. Take care here.
In your AJAX call, you should submit the form data, to the URL associated with your CreateView. I can't see your urls.py, but for example:
$.ajax({
type: "POST",
url: "{% url 'course-create' %}",
data: $('#create-course-form').serialize(),
...
You also need to make sure the form doesn't get submitted with an ordinary POST request (you want to use AJAX), by using preventDefault():
$('#create-course-form').submit(function(e){
e.preventDefault();
...
Putting it all together, back in your Createcourse view, you should define the form_valid(self) method, so that you can add in the user info. As you are using AJAX, you need to return a JsonResponse. E.g.:
def form_valid(self, form):
if self.request.is_ajax():
self.object = form.save(commit=False)
self.object.user = request.user
self.object.save()
return JsonResponse({'success':True})
else:
return super(CreateView, self).form_valid(form)
You also need to handle the situation in which your form is invalid as follows:
def form_invalid(self, form):
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return super(CreateView, self).form_invalid(form)
Finally, you will need to handle the response in your JavaScript. Success doesn't necessarily mean the form was valid and the course was created. If there are errors, you will need to display them to the user.
Update: You have two URLs both called 'create_view'. Remove the second one. Everything can be done from the one CreateView (Createcourse). In order to still have access to 'members', define get_context_data() as follows:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["members"] = Q3Sign.objects.all()
return context
I would like to update my list after adding some inputs through a form but i cannot see my updated list. I see the existing items in my list ,but when i add a new item it does not appear on the list. I can manually add it using the admin pannel and view it in the list(a whole different path),but not with the form i created to take input and update the list. I was able to query my database and input from the form is not getting written to the database, that's why its not displaying any changes.Below is my code
models.py
class BlogPost(models.Model):
notes = models.CharField(max_length = 1000000000000000000000000000)
date = models.DateTimeField(auto_now_add=True)
done = models.BooleanField(default=False)
def __str__(self):
return self.notes
form.py
from blog.models import BlogPost
class BlogForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['notes', 'done',]
views.py
from django.shortcuts import render,redirect
from django.http import HttpResponse,HttpResponseRedirect,HttpRequest
from blog.models import BlogPost
from blog.form import BlogForm
def home(request):
context = {
'welcome_text': 'Welcome to the home page. View some more stuff soon'
}
return render(request,'home.html', context)
def blogpost(request):
if request.method == "POST":
form = BlogForm(request.POST)
if form.is_valid():
if form.save():
message.success(request, "the task was added")
return redirect('blogpost')
else:
all_blogs = BlogPost.objects.all
return render(request, 'blog.html',{'the_blogs': all_blogs } )
blog.html
{%extends 'base.html' %}
{% block title%}
<title> Blog </title>
{% endblock title%}
{%block content %}
<div class="container">
<br>
{%for message in messages%}
{{message}}
{% endfor %}
<form method = 'POST'>
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" name = 'blog' placeholder = 'new blog' >
</div>
<button type="submit" class="btn btn-primary">Add Blog</button>
</form>
<br>
<table class="table table-hover table-dark">
<thead>
<tr>
<th scope="col">Blog </th>
<th scope="col">Done</th>
<th scope="col">Date</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{% for item in the_blogs %}
{% if item.done %}
<tr class="table-success">
<td >{{item.notes}}</td>
<td >Not-Completed</td>
<td>{{item.date}}</td>
<td>edit</td>
<td>delete</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{%endblock content%}
if you need more information regarding this, here is a link to my GitHub repository with more code.
https://github.com/wfidelis/Django-App
You have to correct the code indentation and the get call part, pass the form to context object and call it with double curly brackets on templates, also add an action attribute to the template.
def blogpost(request):
all_blogs = BlogPost.objects.all()
if request.method == "POST":
form = BlogForm(request.POST)
if form.is_valid():
if form.save():
message.success(request, "the task was added")
return redirect('blogpost')
else:
form = BlogForm()
return render(request, 'blog.html',{'form': form, 'the_blogs': all_blogs } )
<form method='POST' action="">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Add Blog</button>
<form/>
When you add a blog, don't redirect, try rendering the page with the new list the same as how you did it here:
all_blogs = BlogPost.objects.all
return render(request, 'blog.html',{'the_blogs': all_blogs } )
or try returning new object created as JSON format to the front-end (as a response of the POST request) and front-end will add it to the HTML with jQuery or JS
I'm currently working on a fairly simple django project and could use some help.Currently I am stuck on saving form using checkboxes.
I have the following models with a ManyToMany and through relationship:
class ProfileMatch(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,unique=True)
profiles = models.ManyToManyField(UserProfile,blank=True)
def __unicode__(self):
return "Profile id: %s" %(self.user.id)
I created a HTML form for this with checkbox .Selected profiles_id should save with associate user_id
<form action="." method="POST" class="post-form">{% csrf_token %}
<thead>
<th>Select</th>
<th>Profile-ID</th>
</thead>
<tbody>
{% for user in userprofiles %}
<tr>
<label class="checkbox">
<input type="checkbox" name="user" data-toggle="checkbox" value="{{ user.pk }}">
</label>
<td>{{ user.profile_id }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<button type="submit" class="save btn btn-default">Add Selected </button>
</form>
And a simple view to save the form:
def PremuiumUserProfileSelectList(request, pk):
match = ProfileMatch.objects.get(pk=pk)
if request.method == 'POST':
if request.POST.getlist("user", None):
checked = request.POST.getlist("user", None)
premium_user = User.objects.get(pk=pk)
m = match(user=premium_user, profiles=checked)
m.save()
else:
return render(request, "premiumuser/selected_list.html", context)
else:
return render(request, "premiumuser/selected_list.html", context)
This doesn't saves the form.Form fields were rendered and all selected profiles_id's are showing in a list .How do I save this Form ?I want to save all selected checkbox values in associated user.How do I save it?
You just do, assuming checked is list of ids.
match.profiles.add(*checked)
I have a table with a user as a foreign key. I'm displaying the data in a template.
I'd like the user to be able to edit or delete the data. I know that there's a save() method for doing this, but I don't understand how to access a particular row. If I have the following model:
class Inventory(models.Model):
item = models.CharField(max_length=20, blank=True)
needs_repairs = models.BooleanField(default=True)
date = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self):
return '%s %s'%(self.item, self.needs_repairs)
And here's my form:
class InventoryForm(ModelForm):
class Meta:
model = Inventory
fields = '__all__'
And a view:
def inventory(request):
model = Inventory
stuff = Inventory.objects.all()
form = InventoryForm(data = request.POST)
if request.method == "POST":
if form.is_valid():
obj = form.save(commit=False)
obj.save()
# return redirect('index')
else:
form = InventoryForm()
context = RequestContext(request)
return render_to_response('inventory.html', {
'form':form, 'stuff':stuff
}, RequestContext(request))
And my template that collects and displays data:
<div>
<div class="formfloatleft">
<h2>Truck Inventory </h2>
<div class="tablewrap">
<table class="gradienttable">
<thead>
<tr>
<th><p>Whatcha got?</p></th>
<th><p>Needs Repairs</p></th>
<th><p>Change</p></th>
</tr>
</thead>
<div class="datatables">
{% for things in stuff %}
<tr class="datarow">
<td>{{things.item}}</td>
<td>{{things.needs_repairs}}</td>
<td>
<form method="post">
{% csrf_token %}
<input type="submit" value="edit or remove me">
</form>
</td>
</tr>
{% endfor %}
</div>
</table>
</div>
</div>
<div class='formfloatright' >
<h2>Add stuff</h2>
<form action="" method="post">
{% csrf_token %}
<ul>
{{ form.as_ul}}
</ul>
</ul>
<input type="submit" value="Save" />
</form>
</div>
</div>
I've tried setting up a function which was called when the user clicked the edit button. This didn't work.
def delete_item(item_id):
thing = Inventory.objects.get(pk=id)
thing.item = None
thing.save()
It didn't work, and then I wound up with circuitous errors. I've deleted it, and can't replicate them (sorry).
How can I allow a user (who has permissions) to select and edit a row using the provided button? Let's say one of the items gets repaired or breaks, for example. I've read the docs, and googled extensively, and I'm still confused about how this is done.
Thanks so much.
This may be giving you Integrity error, I Think so error will be..
null value in column "item" violates not-null constraint
Try this -
def delete_item(item_id):
thing = Inventory.objects.get(pk=id)
thing.item = ''
thing.save()
OR
Inventory.objects.filter(id=id).update(item='')
Hope this will work for you.