I wanted to consult about a question I have, in my system I want this view to give me the products selected by their primary key that would be id, this is done with the form that is in a toggle window
enter image description here
views.py
def add(request):
cart = get_or_create_cart(request)
productos = Producto.objects.get(pk=request.POST.get('producto_id'))
cart.productos.add(productos)
return render(request, 'carts/add.html', {
'productos': productos
})
Models.py
class Cart(models.Model):
cart_id = models.CharField(max_length=100, null=False, blank=False, unique=True)
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
productos = models.ManyToManyField(Producto)
subtotal = models.DecimalField(default=0.0, max_digits=8, decimal_places=2)
total = models.DecimalField(default=0.0, max_digits=8, decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.cart_id
HTML
{% csrf_token %}
<form action="{% url 'Carts:add' %}" method="post">
<input type="hidden" name="producto_id" value="{{ producto.id }}">
<button type="submit" class="btn btn-warning">Agregar al carrito</button>
</form>
Your request method is GET. In the view, try using request.GET.get(arg) instead of POST.
PS You can set the second argument to empty, which is request.GET.get('arg', None) or request.GET.get('arg', ' '). Also, try to use filter() instead of get().
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 have this model which represents the values users submit through a form when making an applying for sponsorship.
class ApplicationData(models.Model) :
class Status(models.TextChoices):
REJECTED = 'Rejected'
PENDING = 'Pending'
ACCEPTED = 'Accepted'
"""Define table for Applications in database"""
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
organisationName = models.CharField(max_length=200, null=True, blank=True)
projectTitle = models.CharField(max_length=200, null=True, blank=True)
CH_OSCR_number = models.CharField(max_length=20, unique=True, blank=True, null=True, )
projectDesc = models.TextField(max_length=300, null=True, blank=True)
userGroupDesc = models.TextField(max_length=300, null=True, blank=True)
learningOpp = models.TextField(max_length=300, null=True, blank=True)
keyPartnersWork = models.TextField(max_length=300, null=True, blank=True)
projImpactClimate = models.TextField(max_length=300, null=True, blank=True)
projSupportLocBus = models.TextField(max_length=300, null=True, blank=True)
proContribution = models.TextField(max_length=300, null=True, blank=True)
length = models.IntegerField(null=True, blank=True)
application_complete = models.BooleanField(default=False)
date_of_application = models.DateField(null=True, blank=True)
reviewed = models.BooleanField(default=False)
app_status = models.TextField(choices = Status.choices, default = Status.PENDING)
On the system there are 3 different user types. Once an applicant submits an application the staff users can view the submitted application details on a dedicated page. What I'm trying to do is to add a form on that page where the staff will have the ability to change the status of the application (app_status on the model).
Here are my efforts:
Here the is the form to update the field.
class UpdateAppStatus(forms.ModelForm):
class Meta:
model = ApplicationData
fields = ('app_status',)
labels = {'app_status':'Change application status?'}
This is the view - it displays the application details and im also trying to add this functionality to update the status.
def view_application_status(request, id):
admin = True if request.user.is_superuser else False
application = ApplicationData.objects.get(id = id)
application_form = ApplicationForm(instance=application)
comments = Comments.objects.filter(application = application)
if request.user.is_staff:
statusform = UpdateAppStatus()
if request.method == 'POST':
satusform = UpdateAppStatus(request.POST)
if satusform.is_valid():
statusform.save()
else:
print(satusform.errors)
return render(request, 'fund/application_view.html', {'application':application, 'application_form' :application_form, 'comments':comments, 'admin':admin,'statusform':statusform})
print(comments)
for comment in comments:
print(comment.comment)
else:
return render(request, 'fund/application_view.html', {'application':application, 'application_form' :application_form, 'comments':comments, 'admin':admin})
And here the is html part:
<main role="main" class="inner cover">
<div class="container-fluid">
<div class="cover-container d-flex h-100 p-3 mx-auto flex-column">
<h1 class="cover-heading text-center">Application Status</h1>
<div class="cover-container d-flex h-100 p-3 mx-auto flex-column">
{% if request.user.is_staff %}
<form id = "ReviewForm" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
<label for="app_status"><strong>{{statusform.app_status.label}}</strong></label>
{{ statusform.app_status }}
<input type="submit" value="Submit" class="btn btn-primary" onclick="">
</form>
{% endif %}
</div>
So what I'm trying to achieve is for the staff to change the value of the field app_status using this form that is visible on the view application status page.
I believe the issue is in the view function but I did not manage to find a solution.
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?
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
im new with Django and Python, and im still confuse about how to prepopulate values from manytomany field related lookup as my question in Prepopulate tabularinline with value from related lookup in manytomany field
here is my model:
class Product(models.Model):
product_name= models.CharField(max_length=50)
price = models.DecimalField(max_digits=10, decimal_places=2, default=Decimal('0.00'))
tax_per_item = models.DecimalField(max_digits=10, null=True, blank=True, decimal_places=2, default=Decimal('0.00'))
discount_per_item = models.DecimalField(max_digits=10, null=True, blank=True, decimal_places=2, default=Decimal('0.00'))
class Order(models.Model):
produks = models.ManyToManyField(Product, verbose_name=u"Kode Produk")
no_customer = models.ForeignKey(Customer, null=True, blank=True, related_name='%(class)s_kode_cust')
def order_view(request):
if 'enter' in request.POST:
#response to tabular.html template
return HttpResponseRedirect('/admin/POS/Pemesanan/inline')
class Foo(models.Model):
product = models.ForeignKey(Product, editable=False)
pemesanan = models.ForeignKey(Order)
quantity = models.IntegerField()
price = models.IntegerField()
discount = models.IntegerField()
tax = models.IntegerField()
and here is my admin:
class PemesananAdmin(admin.ModelAdmin):
fieldsets = (
('Customer in Time (Person)', {
'fields': ('no_customer',),
}),
('Date', {
'fields' : ('date', 'delivery_date',),
}),
('Order Details', {
'fields' : ('produks',),
}),
)
search_fields = ['produks', 'no_customer']
raw_id_fields = ('produks', 'no_customer',)
related_lookup_fields = {
'fk': ['no_customer'],
'm2m': ['produks'],
}
inlines = [
FooInline,
]
class FooInline(admin.TabularInline):
model = Foo
template = 'admin/POS/Pemesanan/inline/tabular.html'
extra = 0
allow_add = True
and here is my change_form override template:
{% extends "admin/change_form.html" %}
{% block after_field_sets %}{{ block.super }}
<form action="" method="post">
<input type="submit" name="enter" value="Enter" />
</form>
{% endblock %}
But, still nobody can tell me how :(. (If you please response to my question on that page). And now, im confusing about 2 problems:
1. I want my submit button in change_form to redirect to change_form too a.k.a in the same page need no refresh page (not to change_list page or the actual submission).
2. How can i get instances of related lookup 'produks' fieldset (manytomany) from submit button so that i can access parent values (Class Product) and prepopulate all to tabularinline (Class Foo or intermediary class)?
FYI, submit button is below all fieldsets.
Anyone help me please :(. Thank you for your kindly responses :).
your problem is, that this
<form action="" method="post">
<input type="submit" name="enter" value="Enter" />
</form>
will just send your submit-button back to your server.
the form-tag needs to sorround every form-element.
just remove: <form action="" method="post"> and </form>
and it may work.
as i understand you correctly you want to display an order (Order) and its items (Foo)?
my naive solution would be:
class Product(models.Model):
...
class Order(models.Model):
products = models.ManyToManyField(Product, through='Item')
class Item(models.Model):
order = models.ForeignKey(Order)
product = models.ForeignKey(Product)
quantity = models.IntegerField()
...
and the admin could be as simple as this:
class ItemInline(admin.TabularInline):
model = Item
class OrderAdmin(admin.ModelAdmin):
inlines = (ItemInline,)
you need to test that, as i cant (actually)