How do I achieve the below:
#login_required
def close_auction(request,listing_id):
listing = Listing.objects.get(pk=listing_id)
if request.method == "POST":
listing.Auction_closed = True
**Disable the Bids on the Listing And display some message such as "The auction is Closed"**
return render(request, "auctions/index.html",{
"listing": Listing.objects.get(pk=listing_id),
"user": User.objects.get(pk=request.user.id),
"owner": listing.owner
})
Below is my code in index.html:
<!-- if the user is the one who created the listing:
they can close the listing
go to the close_auction view to close
-->
{% if user == owner %}
<form action="{% url 'close_auction' listing.id %}" method="post">
{%csrf_token%}
<button>Close this Listing</button>
</form>
{% endif %}
Below is my models.py:
class Listing(models.Model):
Title = models.CharField(max_length=64)
Description = models.TextField(max_length=500)
Category = models.CharField(max_length=16)
Starting_Bid = models.IntegerField()
Image = models.ImageField()
Auction_closed = models.BooleanField(default=False)
#def bid(self):
#return self.Starting_Bid
class User(AbstractUser):
watchlist = models.ManyToManyField(Listing, blank= True, related_name="watcher")
listing_owner = models.ForeignKey(Listing,on_delete=models.CASCADE,related_name="owner",null=True)
class Bid(models.Model):
Bid_amount = models.IntegerField()
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="bids")
bid_placed_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bid_placer", null=True)
What I am trying to achieve here:
If the user is the owner of the listing then he/she should be able to 'close the listing'.
Once the listing is closed, the 'Place a Bid' form should be disabled and some message should be shown instead.
Related
urls.py
...
path('restaurant/menu/', r_view.Menu, name='menu'),
...
menu.html
<form method="POST" id="menuForm" autocomplete="off" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-inline">
<div class="form-group mb-4">
{{ form.item|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.itemImage|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.price|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.category|as_crispy_field }}
</div>
</div>
<button type="submit" class="col-md-12 myBtn">Submit</button>
</form>
views.py
def Menu(request, restaurantID):
restaurant = get_object_or_404(Restaurant_Account, restaurantID=restaurantID)
form = MenuForm()
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.restaurant = restaurant
instance.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
context = {'form':form}
return render(request, 'restaurant/menu.html', context)
forms.py
class MenuForm(forms.ModelForm):
restaurantID = Restaurant_Account.objects.filter(restaurantID='restaurantID')
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
models.py
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
restaurantID = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
menuID = models.AutoField(primary_key=True)
restaurantID = models.ForeignKey(Restaurant_Account, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=[('', 'Choose category'),('Appetizer', 'Appetizer'),('Entree', 'Entree'),('Drink', 'Drink'),('Dessert', 'Dessert'), ('Side', 'Side')])
def __str__(self):
return self.item
I'm new to Django.
I made a form for saving menu data. If the user fills the form and click the submit button every data should be saved in the Menu table. I have no idea how to save restaurantID, which is a foreign key that refers to the Restaurant table, automatically. (By automatically I mean without the user entering input) Can somebody help me with this?
You haven't need to do all these things, if you have made restaurantID a foreign key while defining the model that is Menu, django itself handles it.
Below code might work for you:
forms.py
class MenuForm(forms.ModelForm):
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
views.py
def menu(request):
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
else:
form=MenuForm()
return render(request, 'restaurant/menu.html', {'form':form})
optional: You also don't need to write this line menuID = models.AutoField(primary_key=True) in Menu model, as django makes id column by default for AutoField.
Update:
Make your models.py in this way:
MY_CHOICES=[
('', 'Choose category'),
('Appetizer', 'Appetizer'),
('Entree', 'Entree'),
('Drink', 'Drink'),
('Dessert', 'Dessert'),
('Side', 'Side')
]
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
restaurant= models.ForeignKey(Restaurant, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=MY_CHOICES)
def __str__(self):
return self.item
Remove your AutoField, django by default make id which is primary key.
Don't forget to run makemigrations and migrate, after doing this, if it still gives error, so comment your all models and then run.
I'm creating an ebay like auction site where users can bid on an item they like and if the bid is higher than the last bid, the bid amount displayed would update to the newest bid.
I want to run validation on the modelform to compare the first amount (that the person that created the listing) inputted with the last bid (that the new user inputted).
The problem is that they are in two different models and I'm not sure how to validate both without an error
FORMS.PY
class BidForm(forms.ModelForm):
class Meta:
model = Bids
fields = ['new_bid']
labels = {
'new_bid': ('Bid'),
}
def clean_new_bid(self):
new_bid = self.cleaned_data['new_bid']
current_bid = self.cleaned_data['current_bid']
if new_bid <= current_bid:
error = ValidationError("New bid must be greater than the previous bid")
self.add_error('new_bid', error)
return new_bid
MODELS.PY
class Auction(models.Model):
title = models.CharField(max_length=25)
description = models.TextField()
current_bid = models.IntegerField(null=False, blank=False)
image_url = models.URLField(verbose_name="URL", max_length=255, unique=True, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
category = models.ForeignKey(Category, max_length=12, null=True, blank=True, on_delete=models.CASCADE)
is_active = models.BooleanField(default=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Meta:
ordering = ['-created_at']
class Bids(models.Model):
auction = models.ForeignKey(Auction, on_delete=models.CASCADE, related_name='bidding', null=True)
user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='bidding')
new_bid = models.IntegerField()
done_at = models.DateTimeField(auto_now_add=True)
VIEWS.PY
#login_required
def make_bid(request, listing_id):
auction = Auction.objects.get(pk=listing_id)
user = request.user
if request.method == 'POST':
bid_form = BidForm(request.POST)
if bid_form.is_valid():
new_bid = request.POST['new_bid']
current_price = Bids.objects.create(
listing_id = listing_id,
user = user,
new_bid = new_bid
)
messages.success(request, 'Successfully added your bid')
return HttpResponseRedirect(reverse("listing_detail", args=(listing_id,)))
else:
bid_form = BidForm(request.POST)
return render(request, 'auctions/details.html', {"bid_form": bid_form})
return render(request, 'auctions/details.html', bid_form = BidForm())
DETAILS.HTML
<p>{{ detail.description }}</p>
<hr>
<p>Current price: ${{detail.current_price}}</p>
<form action="{% url 'make_bid' detail.id %}" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.errors }}
{{ bid_form }}
<input type="submit" class="btn btn-primary btn-block mt-3" value="Place bid">
</form>
I'm having this error
KeyError at /make_bid/2
'current_bid'
Request Method:
POST
Request URL:
http://127.0.0.1:8000/make_bid/2
I'm sure its because I'm trying to compare two different models, but don't know a better way to do this. Could you please direct me or is there a better way to run this bid validation process?
I am working on a project on Django, where user can input values on form and submit using POST request. When form is submitted, datas are not saved in database. How do I implement save data when form is submitted.
Models:
class DataInfo(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
beneficiary_name = models.CharField(max_length=250, blank=True)
beneficiary_bank_name = models.CharField(max_length=250, blank=True)
beneficiary_account_no = models.CharField(max_length=250, blank=True)
beneficiary_iban = models.CharField(max_length=250, blank=True)
beneficiary_routing_no = models.CharField(max_length=250, blank=True)
amount = models.IntegerField(blank=True)
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'DataInfo'
verbose_name_plural = 'DataInfo'
ordering = ['-date']
'''Method to filter database results'''
def __str__(self):
return self.user.username
Views:
#login_required
def TransferView(request):
form = DataForm(request.POST)
if request.method == "POST":
if form.is_valid():
pp = form.save(commit=False)
pp.user = request.user
pp.save()
return redirect('site:transfer_cot')
else:
form = DataForm()
context = {
'form':form
}
return render(request, 'transfer.html', context)
Forms:
class DataForm(forms.ModelForm):
class Meta:
model = DataInfo
fields = ('beneficiary_name', 'beneficiary_bank_name', 'beneficiary_account_no', 'beneficiary_iban', 'beneficiary_routing_no', 'amount')
Template:
<form method="POST" action="{% url 'site:transfer_cot' %}">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-secondary">Submit</button>
</form>
I'm trying to make a user stop adding a book into favorite when they already added and show the message into template.
Here's my class django python:
class User(models.Model):
fname = models.CharField(max_length=255)
lname = models.CharField(max_length=255)
email = models.EmailField()
password = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = UserManager()
class Book(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
uploaded_by = models.ForeignKey(User,
related_name="book_uploaded", on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BookManager()
class Like(models.Model):
u_like = models.ForeignKey(
User, related_name="user_like", on_delete=models.CASCADE)
b_like = models.ForeignKey(
Book, related_name="book_like", on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
And here's my views.py:
def book_info(request, id):
user_who_like = Book.objects.get(id=id).book_like.all()
context = {
'book': Book.objects.get(id=id),
'user': User.objects.get(id=request.session["user_id"]),
'user_who_like': Book.objects.get(id=id).book_like.all(),
'user_uploaded': Book.objects.first().uploaded_by,
}
return render(request, 'book_info.html', context)
def like(request, id):
book = Book.objects.get(id=id)
user = User.objects.get(id=request.session["user_id"])
like = Like.objects.create(u_like=user, b_like=book)
return redirect(f"/books/{book.id}")
Appreciate all your help! Thank you
You can try this:
def like(request, id):
book = Book.objects.get(id=id)
user = User.objects.get(id=request.session["user_id"])
like = Like.objects.get_or_create(u_like=user, b_like=book)
if not like[1]:
message = "Already added to favourite"
return redirect(f"/books/{book.id}")
Here, what get_or_create does is it creates an object if the object is not already present and it returns a tuple, the object itself and a boolean value. If the object is newly created then it will return True otherwise False. You can then send this message on you template in a conventional way.
this is my def:
def like(request, id):
book = Book.objects.get(id=id)
user = User.objects.get(id=request.session["user_id"])
like = Like.objects.get_or_create(u_like=user, b_like=book)
if not like[1]:
messages.error(request,"Already added to favorite",extra_tags="like_error")
return redirect("/books/")
context = {
'like1': like[1],
}
return redirect(f"/books/{book.id}")
and here's my template:
<form action="/books/{{book.id}}/like/" method="post" class="like">
{% csrf_token %}
<button type="submit" class="btn far fa-thumbs-up"></button>
{% if messages %}
<ul class="messages">
{% for message in messages %}
{% if "like_error" in message.tags %}
<li class="text-danger">{{ message }}</li>
{%endif%}
{% endfor %}
</ul>
{%endif%}
</form>
Hi Perhaps someone could point me in the right direction, i am learning Django through Tango with Django and i am also following along with the official Django tutorials as well as creating my own Django app for purchase orders.
I need to understand how I can access the Foreign key details of another Model and save it using forms. Basically my app has Orders and Suppliers when creating an order I can get the supplier foreign key options to appear on the form but when I save it I also want to save with the suppier_name into the orders table currently it just saves with the supplier_id, I have searched through many examples of different scenarios but just can't understand it thanks.
view.py
def add_order(request):
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
form.save(commit=True)
return orders(request)
else:
print(form.errors)
else:
form = OrderForm()
context_dict = {'form':form}
return render(
request,
'purchaseorders/add_order.html',
context_dict
)
model.py
# Create your models here.
class Supplier(models.Model):
supplier_code = models.CharField(max_length=10)
supplier_name = models.CharField(
max_length=100,
unique=True
)
supplier_email = models.EmailField(max_length=100)
supplier_website = models.URLField(max_length=100)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.supplier_name)
super(Supplier,self).save(*args, **kwargs)
def __unicode__(self):
return self.supplier_name
def __str__(self):
return self.supplier_name
class Meta:
verbose_name_plural = "Suppliers"
class Order(models.Model):
supplier = models.ForeignKey(Supplier)
po_number = models.IntegerField(default=0)
ordered_by = models.CharField(max_length=50)
order_date = models.DateTimeField()
supplier_name = models.CharField(max_length=50)
net_value = models.DecimalField(
decimal_places=2,
max_digits=10
)
class Meta:
verbose_name_plural = "Orders"
def __unicode__(self):
return self.po_number
forms.py
from django import forms
from PurchaseOrders.models import Supplier, Order
class SupplierForm(forms.ModelForm):
supplier_code = forms.CharField(
max_length=10,
help_text="Please enter a unique code"
)
supplier_name = forms.CharField(
max_length=100,
help_text="Please enter the Suppliers full name"
)
supplier_email = forms.EmailField(
max_length=100,
help_text="Please enter a email address"
)
supplier_website = forms.URLField(
max_length=100,
help_text="Please enter a website"
)
slug = forms.CharField(
widget=forms.HiddenInput(),
required=False
)
# an inline class to provide additional information on the form
class Meta:
# provide an association between the ModelForm and model
model = Supplier
fields = (
'supplier_code', 'supplier_name',
'supplier_email', 'supplier_website'
)
class OrderForm(forms.ModelForm):
#list all form details except the Foreignkey connection
po_number = forms.IntegerField(
help_text="please enter a PO Number"
)
ordered_by = forms.CharField(
max_length=50,
help_text="please enter your name"
)
order_date = forms.DateTimeField(
help_text="please enter a date of order"
)
#supplier_name = forms.ModelChoiceField(
queryset=Supplier.objects.all()
)
net_value = forms.DecimalField(
decimal_places=2,
max_digits=10,
help_text="please enter a net amount"
)
class Meta:
# provide an association between the ModelForm and model
model = Order
html
{% load staticfiles %} <!-- New line -->
<html>
<head>
<title>Purchase Orders</title>
</head>
<body>
<img src="{% static "purchaseorders/images/po_icon.png" %}"
alt="PO icon" />
<h1>Add a Order</h1>
<form id="order_form" method="post"
action="/PurchaseOrders/add_order/{{ supplier }}">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<ul style="list-style-type:none ">
{% for field in form.visible_fields %}
<li></li>
{{ field.errors }}
{{ field.help_text }}
<li>{{ field }}</li>
{% endfor %}
</ul>
<input type="submit" name="submit" value="Add Order" />
</form>
</body>
</html>
To start with the question as-asked, you could capture this data in the model's save() method:
class Order(models.Model):
[...]
def save(self, *args, **kw):
if self.supplier_id is not None:
self.supplier_name = self.supplier.supplier_name
super(Order, self).save(*args, **kw)
HOWEVER, although there are some cases where the above might be correct (such as if supplier name is expected to change), it is much more typical to simply access a related field through the existing relationship, ex:
myorder.supplier.supplier_name