I am currently working on an e-commerce web app and decided to use the Beginning Django Ecommerce book. I am following the content and implementing it in my own way but i am having some issues with some few functions that are not running.
here are the apps with the files where i think the problem is coming from;
1. cart app models.py:
from django.db import models
from menu_items.models import Item
from smartmin.models import SmartModel
import django.db.models.options as options
options.DEFAULT_NAMES = options.DEFAULT_NAMES + ('augment_quatity','name','price','get_absolute_url','total',)
class OrderItem(SmartModel):
order_id = models.CharField(max_length=50)
date_added = models.DateTimeField(auto_now_add=True)
quantity = models.IntegerField(default=0)
item = models.ManyToManyField(Item)
class Meta:
db_table='order_items'
def __unicode__(self):
return "%s" % (self.order_id)
def total(self):
return self.quatity *self.item.price
def name(self):
return self.item.name
def price(self):
return self.item.price
def get_absolute_url(self):
return self.item.get_absolute_url()
# incase user orders same item twice we jus add on the quantity
def augment_quatity(self, quantity):
self.quatity = self.quantity + int(quantity)
self.save
orders.py in the same app:
from cart.models import OrderItem
#from cart.models import order_id
from menu_items.models import Item
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
import decimal
import random
ORDER_ID_SESSION_KEY = 'order_id'
# get the current user's cart id, sets new one if blank
def _order_id(request):
if request.session.get(ORDER_ID_SESSION_KEY,'') == '':
request.session[ORDER_ID_SESSION_KEY] = _generate_cart_id
return request.session[ORDER_ID_SESSION_KEY]
def _generate_cart_id():
order_id =''
characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*()'
order_id_length = 100
for y in range(order_id_length):
order_id += characters[random.randint(0,len(characters)-1
)]
return order_id
# return all items from the current user's order
def get_order_items(request):
return OrderItem.objects.filter(order_id=_order_id(request))
# add an item to order
def add_to_order(request):
postdata = request.POST.copy()
#get item slug from post data, return blank if empty
# item_slug = postdata.get('item_slug','')
#get quantity added, return 1 if empty
quantity = postdata.get('quantity',1)
# fetch the item or return missing page error_message
i = get_object_or_404(Item,)
# get items in order
order_items = get_order_items(request)
item_in_orders = False
# check to see if item is already in cart
for order_item in order_items:
if order_item.item.id == i.id:
#update the quantity if found
order_item.augment_quantity(quantity)
item_in_order = True
if not item_in_order:
# creat and save a new order item
oi = OrderItem()
oi.item = i
oi.quantity = quantity
oi.order_id = _order_id(request)
oi.save()
2.live app views.py
def show_order(request):
if request.method == 'POST':
postdata = request.POST.copy()
if postdata['submit'] == 'Remove':
order.remove_from_order(request)
if postdata['submit'] == 'Update':
order.update_order(request)
order_items = order.get_order_items(request)
page_title = 'F4L order'
order_subtotal = order.order_subtotal(request)
return render_to_response('public/order.html',context_instance=RequestContext(request))
Template where the functionality is not working,
{% extends "base.html" %}
{% block content %}
{% load menu_tags %}
<div style="height:30px">
{% order_box request %}
</div>
<table summary="Your menu order" id="menu_order">
<caption>Your F4L Orders</caption>
<thead>
<tr>
<th scope="col">Item</th>
<th scope="col">Price</th>
<th scope="col" class="right">Total</th>
</tr>
</thead>
<tfoot>
<tr>
<th class="right" colspan="2">
Order Subtotal:
</th>
<th class="right">
{{order_subtotal}}<span> frw</span>
</th>
</tr>
{% if order_items %}
<tr>
<th class="right" colspan="2">
Checkout Now
</th>
</tr>
{% endif %}
</tfoot>
<tbody>
{% if order_items %}
{% for item in order_items %}
<tr>
<td>
{{ item.name }}
</td>
<td>{{ item.price }}<span> frw</span></td>
<td class="right">
<form method="post" action="." class="order">
<label for="quantity">Quantity:</label>
<input type="text" name="quantity" value="{{ item.quantity }}" id="quantity" size="2" class="quantity" max_length="5" />
<input type="hidden" name="item_id" value="{{ item.id }}" />
</td>
<td>
<input type="submit" name="submit" value="update"/>
</form>
</td>
<td>
<form method="post" action="." class="order">
<input type="hidden" name="item_id" value="{{ item.id }}" />
</form>
</td>
<td>
<form method="post" action="." class="order">
<input type="hidden" name="item_id" value="{{ item.id}}" />
<input type="submit" name="submit" value="Remove" />
</form>
</td>
<td class="right">{{ item.total }}<span> frw</span></td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="2" style="height:30px;">
Your F4L order is empty.
</td>
</tr>
{% endif %}
</tbody>
</table>
{% endblock %}
Now th problem is, the above template code is a page a user redirects to after submitting a form with the quantity of item he/she is buying but that is not happening. After submitting form with for example 10items,i redirect to this page(above _template_), it loads correctly but does not return the information i submitted.
i do understand that this is alot but i have really need your help and will appreciate any sort of help.
In show_order view you should pass your variables to template as dictionary:
...
context_dict = {'order_items': order_items, 'order_subtotal': order_subtotal}
return render_to_response('public/order.html', context_dict, context_instance=RequestContext(request))
Related
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 a ListView that lists all questions from the Question model.
the models.py is:
class Question(models.Model):
question_text = models.CharField(max_length=200, unique=True)
pub_date = models.DateField(verbose_name='date published')
def __str__(self):
return self.question_text
now I want users can edit question_text. I tried this in views.py:
class UpdateDirectry(generic.list.ListView, generic.edit.FormMixin):
model = Question
template_name = 'accounts/editable_directory.html'
form_class = forms.EditListForm
def get_context_data(self, *, object_list=None, **kwargs):
context = super(UpdateDirectry, self).get_context_data()
context['object_list'] = Question.objects.filter(question_text__startswith='Who')
return context
and in the template:
<form method="post">
{% csrf_token %}
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Q</th>
<th scope="col">D</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td><input type="text" value="{{ object.question_text }}"></td>
<td>{{ object.pub_date }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<input type="submit" value="Submit">
</form>
I can edit the question_text but when I click submit button nothing happens (just a white page) and no records change in the database.
How can I really edit records with the submit button?
This is what the template shows:
Update 1: ## this is what I exactly want in view (this image is in admin with list_editable):
enter image description here
How can do the exact thing in a view?
Just use a ModelFormSetView from Django Extra Views:
from extra_views import ModelFormSetView
class UpdateDirectry(ModelFormSetView):
model = Question
template_name = 'accounts/editable_directory.html'
form_class = forms.EditListForm
and in your template:
<form method="post">
{{ formset }}
<input type="submit" value="Submit" />
</form>
You have to import UpdateView from :
from django.views.generic.edit import UpdateView
from django.views.generic.edit import FormMixin
from .forms import EditListForm
class UpdateDirectry(UpdateView, FormMixin):
model = Question
template_name = 'accounts/editable_directory.html'
form_class = EditListForm
I want to display some values which is queried out from mysql in the method within views.py on the web page, but I cannot see that on the web page. see my method in views.py:
def update_delete_customer(request, id):
if request.method == 'POST':
print("TODO")
else:
form = CustomerForm()
if id is None:
print("id is None")
return HttpResponseRedirect('AddressTableMaintain/')
print("----------------")
print(id)
customerList = Customer.objects.raw("select * from customers where customer_id = %s", [int(id)])
customer = list(customerList)[0]
print(customer)
form.customerId = customer.customerId
form.first_name = customer.first_name
form.last_name = customer.last_name
print(customer.customerId)
print(customer.first_name)
print(customer.last_name)
return render(request, 'EditCustomer.html', {'form': form})
return HttpResponseRedirect('AddressTableMaintain/')
I can see the output customer id, first name, last name that are generated by the print function in the console.
Below is the contents of my EditCustomer.html:
{% extends 'base.html' %}
{% block title %} Remove or Update customer {% endblock %}
{% block content %}
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
</style>
<form action="{% url 'RU_customer_post' %}" method="post">
{% csrf_token %}
<table width="50%" align="center">
<tr>
<td>Customer ID</td>
<td>
{{ form.customer_id }}
</td>
</tr>
<tr>
<td>First Name</td>
<td>
{{ form.first_name }}
</td>
</tr>
<tr>
<td>Last Name</td>
<td>
{{ form.last_name }}
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value = "OK" /></td>
</tr>
</table>
</form>
{% endblock %}
My expected result is the value should be bound to web page and displayed, but the actual effect is like below:
So, can someone tell me why and how to fix it?
Replace:
form = CustomerForm()
if id is None:
print("id is None")
return HttpResponseRedirect('AddressTableMaintain/')
print("----------------")
print(id)
customerList = Customer.objects.raw("select * from customers where customer_id = %s", [int(id)])
customer = list(customerList)[0]
with:
if id is None:
print("id is None")
return HttpResponseRedirect('AddressTableMaintain/')
print("----------------")
print(id)
customerList = Customer.objects.raw("select * from customers where customer_id = %s", [int(id)])
form = CustomerForm(list(customerList)[0])
Possibly related: Why are you using raw SQL instead of the much simpler:
customer = Customer.objects.get(pk=id)
which would return the one customer that you are looking for?
I have a table where I save data(description, x, y, result and creation date) and until now everything works.
I thought then to add a column with the author for each saved line eg:
DES| X | Y | RESULT |CREATION DATE| AUTHOR |
hi | 3| 1 | 4 | 24/02/2015 | username |
then I added in models.py auth:
from django.db import models
from django.utils import timezone
from simpleapp.oper import add_divide
from django.conf import settings
class ElementiTab(models.Model):
author = models.ForeignKey('auth.User', null=True, blank=False)
des = models.CharField(max_length=30)
x = models.FloatField()
y = models.FloatField()
res = models.FloatField(default=0)
created_date = models.DateTimeField(default=timezone.now)
def save(self, *args, **kwargs):
self.res = add_divide(self.x, self.y)
super(ElementiTab, self).save(*args, **kwargs)
def __str__(self):
return self.des
UPDATE:
forms.py
from django import forms
from .models import ElementiTab
class ElementiTabForm(forms.ModelForm):
class Meta:
model = ElementiTab
fields = ('des', 'x', 'y')
views.py
#login_required
def tabval(request):
# if this is a POST request we need to process the form data
valori = ElementiTab.objects.filter().order_by('-created_date')
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ElementiTabForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
form.save()
# if a GET (or any other method) we'll create a blank form
else:
form = ElementiTabForm()
return render(request, 'simpleapp/simpleapp.html', {'form': form, 'valori': valori})
#user_passes_test(lambda u: u.is_superuser)
def delete(request, id):
valori_to_delete = get_object_or_404(ElementiTab, pk=id).delete()
return redirect(tabval)
simpleapp.html
{% extends 'registration/base_reg.html' %}
{% block title %}SimpleApp-tabval{% endblock %}
{%block content%}
<h4>TABELLA CON DATI</h4>
<form action="/simpleapp/" method="post">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="LIST" />
</form>
<form action="/simpleapp/" method="DELETE">
{% csrf_token %}
<input type="submit" name="canc" value="RESET" />
</form>
<br />
<br />
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="15%" align="center"> NOME</td>
<td width="15%" align="center"> X </td>
<td width="15%" align="center"> Y </td>
<td width="15%" align="center"> RISULTATO </td>
<td width="15%" align="center"> DATA CREAZIONE </td>
<td width="15%" align="center"> AUTORE </td>
{% for elementi in valori %}
<div class="elementi">
<tr>
<td>{{elementi.des}}</td>
<td>{{elementi.x}}</td>
<td>{{elementi.y}}</td>
<td>{{elementi.res}}</td>
<td>{{elementi.created_date}}</td>
<td>{{elementi.author}}</td>
<td width="1%">
{% if user.is_superuser %}
Delete
{% else %}
<span style='font-size: small'>Only Admin</span>
{% endif %}
</td>
</div>
{% endfor %}
</table>
</div>
{% endblock content %}
The fact is that the admin page displays a drop-down menu from which I (as administrator) can choose one of the registered user and so I add them both in the table of my app and in the db.
How can I make this process automatic? I.e. after the login, you put data in the table and once saved the data, also the username is saved and should not be the administrator to set it.
I searched a similar question here but I have not found one to help me to solve my problem.
I updated my answere, i misenderstood your question.
Change this in your view
if form.is_valid():
# Creating the object without commiting to database
obj = form.save(commit=False)
# Setting the user from request
obj.author = request.user
# Commiting to the database
obj.save()
I want to generate django boolean form(checkbox) by for loop(of django Templates) and call it(to views) to delete checked data.
I writed some codes:
(but it don't work at if request.POST['id_checkbox{}'.format(b.id)]: in views)
my codes:
Template
<form role="form" method="post">
{% csrf_token %}
{% render_field form.action %}
<button type="submit" class="btn btn-default">Submit</button>
<table class="table table-striped text-right nimargin">
<tr>
<th class="text-right"> </th>
<th class="text-right">row</th>
<th class="text-right">title</th>
<th class="text-right">publication_date</th>
</tr>
{% for b in obj %}
<tr>
<td><input type="checkbox" name="id_checkbox_{{ b.id }}"></td>
<td>{{ b.id }}</td>
<td>{{ b.title }}</td>
<td>{{ b.publication_date }}</td>
</tr>
{% endfor %}
</table>
</form>
Views
class book_showForm(forms.Form):
action = forms.ChoiceField(label='go:', choices=(('1', '----'), ('2', 'delete'), ))
selection = forms.BooleanField(required=False, )
def libra_book(request):
if request.method == 'POST':
sbform = book_showForm(request.POST)
if sbform.is_valid():
for b in Book.objects.all():
if request.POST['id_checkbox_{}'.format(b.id)]:
Book.objects.filter(id=b.id).delete()
return HttpResponseRedirect('/libra/book/')
else:
sbform = book_showForm()
return render(request, 'libra_book.html', {'obj': Book.objects.all(), 'form': sbform})
Model
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.CharField(max_length=20)
publication_date = models.DateField()
how can i use request.POST to understand that what is value of the checkbox(True or False)?
try to change your checkbox to this
<input type="checkbox" name="checks[]" value="{{ b.id }}">
then on your view,something like this
list_of_checks = request.POST.getlist('checks') # output should be list
for check_book_id in list_of_checks: # loop it
b = Book.objects.get(id=check_book_id) # get the object then
b.delete() # delete it
I find the answer that i must use request.POST.get('id_checkbox_{}'.format(b.id), default=False) Instead of request.POST['id_checkbox_{}'.format(b.id)]
because request.POST['id_checkbox_{}'.format(b.id)] [or request.POST.__getitem__('id_checkbox_{}'.format(b.id))] Raises django.utils.datastructures.MultiValueDictKeyError if the key does not exist.
and must set defout request.POST.get('id_checkbox_{}'.format(b.id), default=False)
see HttpRequest.POST here
and see QueryDict.get(key, default=None) and QueryDict.__getitem__(key) QueryDict.get(key, default=None)