How to change status of the model in Django - python

I'm building a small to-do list project using Django, the to-do list has tasks
divided into to-do, in-progress and done, I want to move to-do tasks from todo list to in-
progress list by changing its status, so I gave the to-do model 3 status, and below in views.py I specified a method to change the status, but it seems not work, I'm not sure how to set the status. Any
help would be appreciated.
models.py
'''
class Todo(models.Model):
status_option = (
('to_do', 'to_do'),
('in_progress', 'in_progress'),
('done', 'done'),
)
status = models.CharField(max_length=20, choices=status_option, default='to_do')
project = models.ForeignKey(Project, on_delete=models.CASCADE)
name = models.CharField(max_length=20)
create_date = models.DateTimeField(auto_now_add=True)
start_date = models.DateTimeField(default=datetime.datetime.now)
due_date = models.DateTimeField(default=datetime.datetime.now)
details = models.TextField()
def __str__(self):
return self.status
'''
views.py
'''
def add_to_progress(request, todo_id, project_id):
todo = Todo.objects.get(id=todo_id)
project = Project.objects.get(id=project_id)
if request.method != 'POST':
form = dragTodoForm()
else:
form = dragTodoForm(request.POST)
Todo.objects.filter(id=todo_id).update(status='in_progress')
context = {'form', form, 'todo', todo, 'project', project}
return render(request, 'todo_lists/new_progress.html', context)
def add_to_done(request, todo_id, project_id):
todo = Todo.objects.get(id=todo_id)
project = Project.objects.get(id=project_id)
if request.method != 'POST':
form = dragTodoForm()
else:
form = dragTodoForm(request.POST)
Todo.objects.filter(id=todo_id).update(status='done')
context = {'form', form, 'todo', todo, 'project', project}
return render(request, 'todo_lists/new_done.html', context)
'''
views.py
'''
def drag(request, project_id):
project = Project.objects.get(id=project_id)
todo = Todo.objects.filter(status='to_do')
progress = Todo.objects.filter(status='in_progress')
done = Todo.objects.filter(status='done')
context = {'todo', todo, 'progress', progress, 'done', done, 'project',
project}
return render(request, 'todo_lists/project.html', context)
'''

I solved the problem using below strategy:
models.py
'''
class Todo(models.Model):
status_option = (
('to_do', 'to_do'),
('in_progress', 'in_progress'),
('done', 'done'),
)
status = models.CharField(max_length=20, choices=status_option, default='to_do')
# todo_list's content
team = models.ForeignKey('Team', on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
name = models.CharField(max_length=20)
create_date = models.DateTimeField(auto_now_add=True)
start_date = models.DateTimeField(default=datetime.datetime.now)
due_date = models.DateTimeField(default=datetime.datetime.now)
project_code = models.CharField(max_length=20)
details = models.TextField()
def __str__(self):
return self.status
# return self.team['team'].queryset
def update_status(self):
if self.status == 'to_do':
self.status = 'in_progress'
elif self.status == 'in_progress':
self.status = 'done'
self.save()
'''
views.py
'''
def progress(request, pk):
to = get_object_or_404(Todo, pk=pk)
to.update_status()
return redirect(reverse('todo_lists:project', kwargs={'project_id':
to.project.pk}))
'''

Related

How do I fail the booking if the booked boolean field is set to True in django?

I am having trouble making if/else work in my django app, I want to check if a listing is booked, booked is a boolean field and the listing is a foreign key to the Booking class where the user selects a listing to book. Now I just want to know how that foreign key can be checked if the listing is booked so it fails to book and gives an error.
views.py
#login_required
def profile(request):
if request.method == "GET":
tickets = models.Booking.objects.all().filter(user=request.user)
return render(request, "profile.html", {'form': forms.BookingForm(), 'tickets': tickets})
else:
try:
form = forms.BookingForm(request.POST)
new_ticket = form.save(commit=False)
new_ticket.user = request.user
new_ticket.save()
messages.success(request, 'Booking Created Successfully')
return redirect('profile')
except ValueError:
return render(request, 'profile.html', {'form': forms.BookingForm()})
models.py
class Listing(models.Model):
title = models.CharField(max_length=50)
content = models.TextField(max_length=755)
price = MoneyField(max_digits=5, decimal_places=2)
booked = models.BooleanField(default=False)
seller = models.ForeignKey(User, on_delete=models.CASCADE)
# avail_days = models.ForeignKey(Days, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Booking(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
listing = models.ForeignKey(Listing, on_delete=models.CASCADE) # how to check if listing is booked and deny if it is True ?
# day = models.OneToOneField(Days, on_delete=models.CASCADE)
date_booked = models.DateField(auto_now_add=True)
def __str__(self):
return self.user.username
If you want to use booked field in Listing model, you can do this (you can also render Listing objects with booked=False):
views.py
#login_required
def profile(request):
if request.method == "GET":
tickets = models.Booking.objects.all().filter(user=request.user)
return render(request, "profile.html", {'form': forms.BookingForm(), 'tickets': tickets})
else:
try:
form = forms.BookingForm(request.POST)
new_ticket = form.save(commit=False)
# here you can do something like
if new_ticket.listing.booked:
messages.error(request, 'Booked Already')
return redirect('profile')
new_ticket.user = request.user
new_ticket.save()
messages.success(request, 'Booking Created Successfully')
return redirect('profile')
except ValueError:
return render(request, 'profile.html', {'form': forms.BookingForm()})
models.py
class Listing(models.Model):
title = models.CharField(max_length=50)
content = models.TextField(max_length=755)
price = MoneyField(max_digits=5, decimal_places=2)
booked = models.BooleanField(default=False)
seller = models.ForeignKey(User, on_delete=models.CASCADE)
# avail_days = models.ForeignKey(Days, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Booking(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
listing = models.ForeignKey(Listing, on_delete=models.CASCADE) # how to check if listing is booked and deny if it is True ?
# day = models.OneToOneField(Days, on_delete=models.CASCADE)
date_booked = models.DateField(auto_now_add=True)
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
self.listing.booked = True
self.listing.save()
super().save(*args, **kwargs)

MultipleObjectsReturned at /checkout/ get() returned more than one Order -- it returned 2

Hi I'm trying to develop an e-commerce website using Django. I have two models and views on separate folders, one is an order model and view, another is the checkout model and view. The order view creates a new order everytime an item is added to the cart. And the checkout view creates a new billing address. I want to associate the billing address that is created to the order when the checkout form is submitted. But for some reason, it's not happening. It throws an error:
MultipleObjectsReturned at /checkout/
get() returned more than one Order -- it returned 2!
What is the problem?
My orders.models.py:
from django.db import models
from shopping_cart.models import Cart
from django.contrib.auth import get_user_model
from accounts2.models import BillingAddress
STATUS_CHOICES = (
("Started", "Started"),
("Abandoned", "Abandoned"),
("Finished", "Finished"),
)
User = get_user_model()
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
order_id = models.CharField(max_length=120, default='ABC', unique=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
status = models.CharField(max_length=120, choices=STATUS_CHOICES, default="Started")
sub_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
tax_total = models.DecimalField(default=0.00, max_digits=1000, decimal_places=2)
final_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
billing_address = models.ForeignKey(BillingAddress, on_delete=models.SET_NULL, blank= True, null=True)
My orders.views.py:
#login_required
def order(request):
try:
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
except:
the_id = None
return redirect(reverse("myshop-home"))
try:
new_order = Order.objects.get(cart=cart)
except Order.DoesNotExist:
new_order = Order(cart=cart)
new_order.cart = cart
new_order.user = request.user
new_order.order_id = id_generator()
new_order.save()
except:
return redirect(reverse("cart"))
if new_order.status == "Finished":
#cart.delete()
del request.session['cart_id']
del request.session['items_total']
return redirect(reverse("cart"))
context = {"address_form": address_form, "cart": cart}
template = "orders/checkout.html"
return render(request, template, context)
My accounts.models.py:
class BillingAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
street_address = models.CharField(max_length=100)
apartment_address = models.CharField(max_length=100)
country = CountryField(multiple=False)
zip = models.CharField(max_length=100)
class Meta:
verbose_name_plural = "Billing Addresses"
My accounts.views.py:
class CheckoutView(LoginRequiredMixin, View):
def get(self, *args, **kwargs):
the_id = self.request.session['cart_id']
cart = Cart.objects.get(id=the_id)
form = CheckoutForm()
context = {"form": form, "cart": cart}
return render(self.request, "orders/checkout.html", context)
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
try:
order = Order.objects.get(user = self.request.user)
if form.is_valid():
street_address = form.cleaned_data.get('street_address')
apartment_address = form.cleaned_data.get('apartment_address')
country = form.cleaned_data.get('country')
zip = form.cleaned_data.get('zip')
# same_shipping_address = form.cleaned_data.get('same_billing_address')
# save_info = form.cleaned_data.get('save_info')
payment_option = form.cleaned_data.get('payment_option')
billing_address = BillingAddress(
user = self.request.user,
street_address = street_address,
apartment_address = apartment_address,
country = country,
zip = zip
)
billing_address.save()
order.billing_address = billing_address
order.save()
return redirect('checkout')
messages.warning(self.request, "Failed checkout")
return redirect('checkout')
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect('/')
Use Order.objects.filter(user=user).last() to get the newest row or try to remember order's id when creating an order and filter with Order.objects.get(id=id)

Django extending the User model in ECommerce application

I have a django ecommerce project that works fine till I decided to improve it. User place order and every time they place an order they have to always input their details (name, emil, address etc) , I decided to upgrade the application so if user had registered before no need to enter details again .
orders/models.py
from django.db import models
from django.contrib.auth.models import User
from shop.models import Product
from decimal import Decimal
from django.core.validators import MinValueValidator,MaxValueValidator
from coupons.models import Coupons
class order(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
address = models.CharField(max_length=250)
postal_code = models.CharField(max_length=50)
city = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
coupon = models.ForeignKey(Coupons,related_name='orders',on_delete=models.CASCADE ,null=True,blank=True)
discount = models.IntegerField(default=0,validators=[MinValueValidator(0),MaxValueValidator(100)])
class Meta:
ordering = ('-created',)
verbose_name = "order"
verbose_name_plural = "orders"
def __str__(self):
return 'Order {}'.format(self.id)
def get_total_cost(self):
return sum(item.get_cost() for item in self.items.all())
def get_total_cost_after_discount(self):
total_cost = sum(item.get_cost() for item in self.items.all())
return total_cost - total_cost * (self.discount / Decimal('100'))
class OrderItem(models.Model):
order = models.ForeignKey(order,related_name='items',on_delete=models.CASCADE)
product = models.ForeignKey(Product,related_name='order_items',on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10,decimal_places=2)
quantity = models.PositiveIntegerField(default=1)
class Meta:
verbose_name = "OrderItem"
verbose_name_plural = "OrderItems"
def __str__(self):
return '{}'.format(self.id)
def get_cost(self):
return self.price * self.quantity
I create account app and extended django user so that user can register address so that the user does not have to type it every time when place an order.
accounts/models.py
class UserProfile(models.Model):
user = models.OneToOneField(User,related_name='UserProfiles',on_delete=models.CASCADE)
country = models.CharField(max_length=300, default='Saudi Arabia')
city = models.CharField(max_length=100, default='')
phone = models.CharField(max_length=15,default='')
image = models.ImageField(upload_to='profile_image', blank=True)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(null=True)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
and rewrite:
orders/models.py
class order(models.Model):
user = models.ForeignKey(User,on_delete=models.DO_NOTHING)
address = models.ForeignKey(UserProfile,on_delete=models.DO_NOTHING)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
coupon = models.ForeignKey(Coupons,related_name='orders',on_delete=models.CASCADE ,null=True,blank=True)
discount = models.IntegerField(default=0,validators=[MinValueValidator(0),MaxValueValidator(100)])
now my problem is how can I fix the view to show form of user address with information if user entered before or the user fill form with address
views.py
#login_required
def order_create(request):
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
if cart.coupon:
order.coupon = cart.coupon
order.discount = cart.coupon.discount
order.save()
for item in cart:
OrderItem.objects.create(
# user = User.username,
order=order,
product=item['product'],
price=item['price'],
quantity=item['quantity'])
cart.clear()
context = {
'order':order,
}
return render(request, 'created.html',context)
else:
form = OrderCreateForm()
context = {
'cart':cart,
'form':form
}
return render(request, 'create.html',context)
orders/forms.py
from django import forms
from .models import order
class OrderCreateForm(forms.ModelForm):
class Meta:
model = order
fields = ('first_name','last_name','email','address','postal_code','city',)
I don't see your OrderCreateForm, but I'm assuming it has fields that match the ones in UserProfile. If so, try changing the view code to pull data from the profile to populate the initial data:
#login_required
def order_create(request):
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
if cart.coupon:
order.coupon = cart.coupon
order.discount = cart.coupon.discount
order.save()
for item in cart:
OrderItem.objects.create(
# user = User.username,
order=order,
product=item['product'],
price=item['price'],
quantity=item['quantity'])
cart.clear()
context = {
'order':order,
}
return render(request, 'created.html',context)
else:
if request.user and hasattr(request.user, 'UserProfiles'):
profile = request.user.UserProfiles
initial = {
'first_name', request.user.first_name,
'last_name', request.user.last_name,
'email', request.user.email,
'address': profile.address,
'city': profile.city
}
else:
initial = {}
form = OrderCreateForm(initial=initial)
context = {
'cart':cart,
'form':form
}
return render(request, 'create.html',context)

How to create a like functionality in django for a blog

I have to build a blog for my chess club and I would like to make a like functionality for the posts. When the user likes the post the like count increases and the post its shown in the user profile.
Here is what I made so far:
This is my post model:
class Post(models.Model):
title = models.CharField(max_length=100)
overview = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
content = HTMLField()
is_aproved = models.BooleanField(default=False)
# comment_count = models.IntegerField(default = 0)
# view_count = models.IntegerField(default = 0)
slug = models.SlugField(unique=True, blank=True)
likes = models.ManyToManyField(
settings.AUTH_USER_MODEL, blank=True, related_name='post_likes')
author = models.ForeignKey(Author, on_delete=models.CASCADE)
thumbnail = models.ImageField()
categories = models.ManyToManyField(Category)
featured = models.BooleanField()
previous_post = models.ForeignKey(
'self', related_name='previous', on_delete=models.SET_NULL, blank=True, null=True)
next_post = models.ForeignKey(
'self', related_name='next', on_delete=models.SET_NULL, blank=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={
'id': self.id
})
def get_update_url(self):
return reverse('post-update', kwargs={
'id': self.id
})
def get_delete_url(self):
return reverse('post-delete', kwargs={
'id': self.id
})
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
#property
def comment_count(self):
return Comment.objects.filter(post=self).count()
#property
def view_count(self):
return PostView.objects.filter(post=self).count()
And this is my view:
def post(request, id):
category_count = get_category_count()
most_recent = Post.objects.order_by('-timestamp')[:3]
post = get_object_or_404(Post, id=id)
if request.user.is_authenticated:
PostView.objects.get_or_create(user=request.user, post=post)
form = CommentForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.instance.user = request.user
form.instance.post = post
form.save()
return redirect(reverse("post-detail", kwargs={
'id': post.pk
}))
context = {
'form': form,
'post': post,
'most_recent': most_recent,
'category_count': category_count,
'form': form
}
return render(request, 'post.html', context)
could you help me to implement this like functionality
You need another model to get liking functionality in Django. Create a like model like this-
class PostLikes(models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(Post)
created = models.DateTimeField(auto_now_add=True)
then create a view to add the instance to the PostLikes model-
def like_others_post(request, post_id):
new_like, created = PostLikes.objects.get_or_create(user=request.user,
post_id=post_id)
if not created:
# you may get and delete the object as the user may already liked this
post before
We are using get or create to avoid duplication of likes. So a user may click multiple times but, a like instance is stored only once.
then add a method to Post model for getting the number of likes-
def Post(models.Model):
...
...
#property
def view_count(self):
return PostLikes.objects.filter(post=self).count()
To find out if the current user already likes the displayed post or not, in your post view-
def post(request, id):
....
....
already_liked = PostLikes.objects.filter(user=request.user, post=post).count()
if number_of_likes > 0:
already_liked = True # pass this variable to your context
else:
already_liked = False # you can make this anything other than boolean
Then by use of Javascript and {{already_liked}}, change your animation of like button in your template.

Update Django Model With Form Field

I am trying to update the quantity of my Inventory model using a Integer form field on the front end. I am able to add a new inventory item, but I want to update existing items. Here is my code:
FROM VIEWS.PY
def view_inventory(request, slug):
if request.method == 'POST':
quantity_add = addQuantity(request.POST)
if quantity_add.is_valid():
cd = quantity_add.cleaned_data
addq=Inventory(quantity = cd.get('quantity'))
addq.save()
quantity_add=addQuantity()
return render(request, 'inv/view_inventory.html', {
'item': get_object_or_404(Inventory.objects.all(), slug=slug),
'form' : quantity_add,
})
FROM MODELS.PY
class Inventory(models.Model):
quantity = models.IntegerField()
name = models.CharField(max_length=150, unique = True)
slug = models.SlugField(unique = True)
date = models.DateTimeField(auto_now_add=True)
description = models.CharField(max_length=250)
category = models.ForeignKey(Category, null=True, blank=True)
def __unicode__(self):
return self.name
#permalink
def get_absolute_url(self):
return ('view_inventory', None, { 'slug' : self.slug })
class Meta:
ordering = ['-date']
FROM URLS.PY
url(r'^(?P<slug>[\w\-]+)/$', 'inv.views.view_inventory', name='view_inventory'),
You only have to get the record and then update it:
def view_inventory(request, slug):
if request.method == 'POST':
quantity_add = addQuantity(request.POST)
if quantity_add.is_valid():
cd = quantity_add.cleaned_data
old_inventory = Inventory.objects.get(id=something here) #id or pk or whatever you want
old_inventory.quantity = cd.get('quantity')
old_inventory.save()
quantity_add=addQuantity()
return render(request, 'inv/view_inventory.html', {
'item': get_object_or_404(Inventory.objects.all(), slug=slug),
'form' : quantity_add,
})

Categories

Resources