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.
Related
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 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'),
I am currently trying to get an edit form working on the same page as a detail view in Django.
I am currently trying out the way as recommended on the docs (i.e. using FormMixin). So, my view looks like this:
class ProductiveMinutesDetail(FormMixin, DetailView):
model = models.ProductiveMinutes
pk_url_kwarg = 'productiveminutes_pk'
form_class = forms.EditForm
def get_success_url(self):
return reverse_lazy('productiveminutes_list')
def get_context_data(self, **kwargs):
context = super(ProductiveMinutesDetail, self).get_context_data(**kwargs)
context['form'] = forms.EditForm(initial={'post': self.object})
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super(ProductiveMinutesDetail, self).form_valid(form)
And my form looks like this:
from django import forms
from . import models
class EditForm(forms.ModelForm):
class Meta:
model = models.ProductiveMinutes
fields = ('name', 'description',)
The model I am using is this:
class Scenario(models.Model):
name = models.CharField(max_length=200)
class ProductiveMinutes(models.Model):
scenario = models.OneToOneField(Scenario)
name = models.CharField(max_length=200)
amount = models.DecimalField(max_digits=50, decimal_places=2)
description = models.CharField(max_length=200)
Using this I can get the form to render on the page but I know I am doing something wrong as the fields are empty when I would like them to be populated with the data that is already present.
Another piece of complexity is that this form should not be editing the amount field of the model just the name and description. The amount value is edited separately from the detail view of this page.
So, I guess my main question is how can I get the form to be populated with the data for the models fields that is already present and then edit it. Ideally functionality like that of the generic UpdateView that Django provides.
I am using Django version 1.10
Any help with this would be much appreciated
Thanks for your time
UPDATE:
My template looks like this:
{% extends 'pages/dashboard.html' %}
{% load i18n humanize crispy_forms_tags %}
{% block content %}
<div>
<h1 class="text-center">Productive Minutes: {{ productiveminutes.name }}</h1>
<div class="row">
<div class="col"></div>
<div class="col-md-8 col-lg-8">
<h3>Edit productive minutes: {{ productiveminutes.name }}</h3>
<form role="form" method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="primaryAction btn btn-primary pull-right" type="submit">{% trans "Submit" %}</button>
</form>
</div>
<div class="col"></div>
</div>
<hr>
<div class="row">
<div class="col"></div>
<div class="col-md-8 col-lg-8">
<h3>Data Records</h3>
<div class="table-responsive">
<table class="table table-bordered">
<thead class="thead-default">
<tr>
<th>ID</th>
<th>Productive Minutes</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ productiveminutes.id }}</td>
<td>{{ productiveminutes.amount|intcomma }}</td>
<td>
<i class="fa fa-pencil"></i>
<i class="fa fa-trash"></i>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col"></div>
</div>
</div>
{% endblock content %}
The example in the docs is for displaying detail for an object and having a separate contact form.
In your case, it sound like you want to display the ProductiveMinutesDetail object, and have a form that allows you to update some of the fields of that same object. In that case, you should just use UpdateView.
class ProductiveMinutesUpdate(UpdateView):
model = models.ProductiveMinutes
pk_url_kwarg = 'productiveminutes_pk'
form_class = forms.EditForm
success_url = reverse('productiveminutes_list')
def get_context_data(self, **kwargs):
context = super(ProductiveMinutesUpdate, self).get_context_data(**kwargs)
# Refresh the object from the database in case the form validation changed it
object = self.get_object()
context['object'] = context['productiveminutes'] = object
return context
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)