Can anyone tell me what's wrong with my code? I am trying to use filter but its showing ''QuerySet' object has no attribute 'enter_the_destination_account_number'. I tried get() but it shows,
get() returned more than one MoneyTransfer -- it returned 14!.
here's some snap of code. Thanks in advance
models.py
class Status (models.Model):
user_name = models.CharField(max_length=150, default=None)
account_number = models.IntegerField()
balance = models.IntegerField()
phone_number= models.CharField(max_length=20, default=0)
class MoneyTransfer(models.Model):
enter_your_user_name = models.CharField(max_length = 150, default = None)
enter_the_destination_account_number = models.IntegerField()
enter_the_destination_phone_number=models.CharField(max_length=20, default=None)
enter_the_amount_to_be_transferred_in_INR = models.IntegerField()
views.py
def TransferMoney(request):
if request.method == "POST":
form = forms.MoneyTransferForm(request.POST)
if form.is_valid():
form.save()
curr_user = models.MoneyTransfer.objects.filter(enter_your_user_name=request.user)
dest_user_acc_num = curr_user.enter_the_destination_account_number #dest_phone number add korte hobe
dest_phone_num= curr_user.enter_the_destination_phone_number
temp = curr_user # NOTE: Delete this instance once money transfer is done
dest_user = models.Status.objects.get(account_number=dest_user_acc_num) # FIELD 1
dest_phn= models.Status.objects.get(phone_number= dest_phone_num)
transfer_amount = curr_user.enter_the_amount_to_be_transferred_in_INR # FIELD 2
curr_user = models.Status.objects.get(user_name=request.user) # FIELD 3
# Now transfer the money!
curr_user.balance = curr_user.balance - transfer_amount
#dest_phn.balance = dest_phn.balance + transfer_amount
dest_user.balance = dest_user.balance + transfer_amount
# Save the changes before redirecting
curr_user.save()
dest_user.save()
temp.delete() # NOTE: Now deleting the instance for future money transactions
return redirect(index)
else:
form = forms.MoneyTransferForm()
return render(request, "epayapp/Transfer_money.html", {"form": form})
The issue is that filter returns a queryset, not an object.
So you cannot access the fields directly from the queryset, what you can do is grab the first element from the queryset and perform the operations you want.
Like this: curr_user = models.MoneyTransfer.objects.filter(enter_your_user_name=request.user).first()
So it'll look like this:
def TransferMoney(request):
if request.method == "POST":
form = forms.MoneyTransferForm(request.POST)
if form.is_valid():
form.save()
# Grab the first object from the queryset
curr_user = models.MoneyTransfer.objects.filter(enter_your_user_name=request.user).first()
dest_user_acc_num = curr_user.enter_the_destination_account_number #dest_phone number add korte hobe
dest_phone_num= curr_user.enter_the_destination_phone_number
temp = curr_user # NOTE: Delete this instance once money transfer is done
dest_user = models.Status.objects.get(account_number=dest_user_acc_num) # FIELD 1
dest_phn= models.Status.objects.get(phone_number= dest_phone_num)
transfer_amount = curr_user.enter_the_amount_to_be_transferred_in_INR # FIELD 2
curr_user = models.Status.objects.get(user_name=request.user) # FIELD 3
# Now transfer the money!
curr_user.balance = curr_user.balance - transfer_amount
#dest_phn.balance = dest_phn.balance + transfer_amount
dest_user.balance = dest_user.balance + transfer_amount
# Save the changes before redirecting
curr_user.save()
dest_user.save()
temp.delete() # NOTE: Now deleting the instance for future money transactions
return redirect(index)
else:
form = forms.MoneyTransferForm()
return render(request, "epayapp/Transfer_money.html", {"form": form})
the filter method on objects does not returned an object as you think. it will return a Queryset object
You have to loop into the results of filter or take an item with first() function for example
def TransferMoney(request):
if request.method == "POST":
form = forms.MoneyTransferForm(request.POST)
if form.is_valid():
form.save()
queryset = models.MoneyTransfer.objects.filter(enter_your_user_name=request.user)
curr_user = queryset.first()
dest_user_acc_num = curr_user.enter_the_destination_account_number #dest_phone number add korte hobe
dest_phone_num= curr_user.enter_the_destination_phone_number
temp = curr_user # NOTE: Delete this instance once money transfer is done
dest_user = models.Status.objects.get(account_number=dest_user_acc_num) # FIELD 1
dest_phn= models.Status.objects.get(phone_number= dest_phone_num)
transfer_amount = curr_user.enter_the_amount_to_be_transferred_in_INR # FIELD 2
curr_user = models.Status.objects.get(user_name=request.user) # FIELD 3
# Now transfer the money!
curr_user.balance = curr_user.balance - transfer_amount
#dest_phn.balance = dest_phn.balance + transfer_amount
dest_user.balance = dest_user.balance + transfer_amount
# Save the changes before redirecting
curr_user.save()
dest_user.save()
temp.delete() # NOTE: Now deleting the instance for future money transactions
return redirect(index)
else:
form = forms.MoneyTransferForm()
return render(request, "epayapp/Transfer_money.html", {"form": form})
get function have to returned only one element or it will raises a exception...
Maybe set account_number and user_name unique in your fields definition for rpeventing this cases
Related
i'm buildint a warehouse management application, i have a product model and an placement for each product, every placement has a volume, once i put a product in a placement, the volume of this placement must be reduced. The problem is when the app finds a placement for the product, the placement volume stay the same
models.py
class Emplacement(models.Model):
address = models.CharField(max_length=25, blank=True)
volume = models.DecimalField(max_digits=10, decimal_places=2, null=True)
class Product(models.Model):
name = models.CharField(max_length=100)
quantity = models.PositiveIntegerField()
is_disponible = models.BooleanField(default=False)
volume = models.DecimalField(max_digits=20, decimal_places=2, null=True)
emplacement = models.ForeignKey(Emplacement, on_delete=models.CASCADE, null=True)
views.py
def product_detail(request, pk):
product = get_object_or_404(Product, id=pk)
if request.method == 'POST':
form = ValidateProductForm(request.POST, instance=product)
if form.is_valid():
product = form.save(commit=False)
product.volume = form.cleaned_data['longueur'] * form.cleaned_data['largeur'] * form.cleaned_data['hauteur']
product.is_disponible = True
all_emplacements = Emplacement.objects.all()
i=1
while i <= product.quantity:
for emplacement in all_emplacements:
if product.volume < emplacement.volume:
product.emplacement = emplacement
emplacement.volume -= product.volume
i+=1
product.save()
return redirect('print-barcode', product.id)
else:
form = ValidateProductForm(instance=product)
context = {
'product': product,
'form': form,
}
return render(request, 'dashboard/product_detail.html', context)
You're not saving the emplacement object.
Try this:
if request.method == 'POST':
form = ValidateProductForm(request.POST, instance=product)
if form.is_valid():
product = form.save(commit=False)
product.volume = form.cleaned_data['longueur'] * form.cleaned_data['largeur'] * form.cleaned_data['hauteur']
product.is_disponible = True
all_emplacements = Emplacement.objects.all()
i=1
while i <= product.quantity:
for emplacement in all_emplacements:
if product.volume < emplacement.volume:
product.emplacement = emplacement
emplacement.volume -= product.volume
emplacement.save()
i+=1
product.save()
return redirect('print-barcode', product.id)
else:
form = ValidateProductForm(instance=product)
Edit
Your Product model indicates that each Product has only ONE Emplacement, since that's where the ForeignKey is. But, a single Emplacement, can have MANY Product objects. ForeignKey is a ManyToOne relationship. When iterating through ALL Emplacements, you are using the SAME Product, and that's why they are all getting the same number in your admin. I'm guessing, but perhaps what you're after is to find the SINGLE appropriate Emplacement model that the specific Product object has, nad then update just that one. In other words, NO iterating at all.
if request.method == 'POST':
form = ValidateProductForm(request.POST, instance=product)
if form.is_valid():
product = form.save(commit=False)
product.volume = form.cleaned_data['longueur'] * form.cleaned_data['largeur'] * form.cleaned_data['hauteur']
product.is_disponible = True
# Here are my proposed changes:
product.save() # Update the product
emplacement = product.emplacement # Get the correct Emplacement
emplacement.volume -= product.volume # Adjust the volume
emplacement.save() # Save the emplacement
return redirect('print-barcode', product.id)
else:
form = ValidateProductForm(instance=product)
I have these models:
class Customers(models.Model):
ID = models.AutoField(primary_key=True)
...
def __str__(self):
return str(self.ID)
class CustomerAddresses(models.Model):
ID = models.AutoField(primary_key=True)
...
CustomerNoID = models.ForeignKey('Customers', on_delete=models.CASCADE)
def __str__(self):
return str(self.ID)
and my view:
def add_customer_view(request):
user_id = request.user.id
last_customerno = Customers.objects.filter(UserID=user_id).order_by('CustomerNo').last()
if not last_customerno:
# return '0001'
last_customerno = 1000
if last_customerno == 1000:
customerno_int = 1000
else:
customerno_int = last_customerno.CustomerNo + 1
# if this is a POST request we need to process the form data
if request.method == 'POST':
customer_form = CustomerForm(request.user.id, request.POST)
customer_address_form = CustomerAddressesForm(request.user.id, request.POST)
if customer_form.is_valid():
new_customer = customer_form.save(commit=False)
new_customer.save()
if customer_address_form.is_valid():
new_address = customer_address_form.save(commit=False)
new_address.CustomerNoID = new_customer
new_address.save()
return HttpResponseRedirect('/backend/kunder/')
else:
customer_form = CustomerForm(request.user.id, initial={'CustomerNo': customerno_int})
customer_address_form = CustomerAddressesForm(request.user.id)
return render(
request,
'backend/add_customer.html',
{
'title': 'WestcoastShop - Backend',
'customer_form': customer_form,
'customer_address_form': customer_address_form
}
)
But just the Customer is creating not the address I think the form is missing the CustomerNoID and I think I got the right way but after 6 hrs I give up maybe here is a smart guy how finds the error.
regards.
I changed the form and added the second one in a modal so I can save the two models nondependent.
i'm trying to make a simple inventory app but i'm have trouble with restock logic for instance if i have a new stock bought with diffrent price than the first one i want just get the average price on the whole stock in shell works fine but when i go to my form i always get the form input instead of the desired value, after some investigation i found out that i'm grabbing the instance data using request.POST.get and even before the save quantity = item.quantity!! my question now is how can i grab my input and the instance separately
##models
class Supply(models.Model):
name = models.CharField(max_length=100, unique=True)
quantity = models.PositiveIntegerField()
price = models.DecimalField(max_digits=11, decimal_places=2)
created = models.DateField(auto_now_add=True)
last_modefied = models.DateField(auto_now=True)
def __str__(self):
return self.name
##form
class SupplyForm(forms.ModelForm):
class Meta:
model = Supply
fields = ["name", "quantity", "price"]
#view
def add_supply(request):
form = SupplyForm()
if request.POST:
# getting form input data
name = request.POST.get("name")
quantity = request.POST.get("quantity")
price = request.POST.get("price")
# getting Supply instance
item = Supply.objects.get(name=name)
# instantiating the form
form = SupplyForm(request.POST, instance=item)
if form.is_valid:
# Logic
old_supply = item.quantity * item.price
new_supply = int(quantity) * int(price)
new_quantity = item.quantity + int(quantity)
item.price = (old_supply + new_supply) / new_quantity
item.quantity = new_quantity
form.save()
return redirect("project_list")
return render(request, "restock.html", {"form": form})
found this answer to who ever might need it :
1st remove modelform and make a form.Forms with 2 new fields something like that
#forms
class RestockForm(forms.Form):
name = forms.CharField(max_length="30")
quantity = forms.IntegerField(min_value=0)
price = forms.DecimalField(max_digits=11, decimal_places=2)
new_quantity = forms.IntegerField(min_value=0)
new_price = forms.DecimalField(max_digits=11, decimal_places=2)
#views
def add_supply(request, pk):
#getting the object
item = get_object_or_404(Supply, pk=pk)
# instantiating the form on using initial since its not a model form
form = RestockForm(initial={"name": item.name, "quantity": item.quantity, "price": item.price})
if request.POST:
# getting form extra input data
quantity = request.POST.get("new_quantity")
price = request.POST.get("new_price")
form = RestockForm(request.POST,)
if form.is_valid():
old_supply = item.quantity * item.price
new_supply = int(quantity) * int(price)
_quantity = item.quantity + int(quantity)
item.price = (old_supply + new_supply) / _quantity
item.quantity = _quantity
# important need to save the object
item.save()
return redirect("project_list")
return render(request, "restock.html", {"form": form})
#urls
path('restock/<int:pk>', stock_views.add_supply, name="restock"),
views.py
def patient_num(request):
if request.method == 'POST':
form = EditToBeSaveForm(request.POST)
if form.is_valid():
num = form.cleaned_data['病人编号']
new_p = Patient.objects.get(p_number=num)
if new_p:
new_p.p_name = form.cleaned_data['姓名']
new_p.p_sex = form.cleaned_data['性别']
new_p.p_age = form.cleaned_data['年龄']
new_p.p_tel_number = form.cleaned_data['电话号码']
new_p.save()
return render(request, 'polls/patient_edit.html')
else:
form = EditToBeSaveForm()
return render(request, 'polls/patient_num.html', {'form': form})
models.py
class Patient(models.Model):
sex_choice = (
('男', '男'),
('女', '女'),
)
p_name = models.CharField(max_length=100, default='template')
p_age = models.IntegerField(default=0)
p_number = models.IntegerField(default=0)
p_tel_number = models.IntegerField(default=0)
p_sex = models.CharField(choices=sex_choice, max_length=2, default='男')
forms.py
class EditForm(forms.Form):
病人编号 = forms.IntegerField()
class EditToBeSaveForm(forms.Form):
sex_choice = (
('male', '男'),
('female', '女'),
)
病人编号 = forms.IntegerField(label='你要修改的病人编号')
姓名 = forms.CharField(max_length=100)
年龄 = forms.IntegerField()
电话号码 = forms.IntegerField()
性别 = forms.ChoiceField(choices=sex_choice)
after i populate the form and submit it, the view didn't update the database instance,why?
i can do it one by one in shell as below.
new confuse!when i populate the form with invalid value,for example, an inexistent id of Patient object,it will still render the template,why?
It seems to me your problem is that you never reach the code under the if form.is_valid() of your patient_num view. Try to add some prints after the if form.is_valid() clause and make sure your form is valid. It is expected that your model will not be updated if your form is not valid.
Your problem here that you are passing request to form instead request.POST
form = EditToBeSaveForm(request.POST)
i put some 'print stuff' in my view and disvocer sth:
def patient_num(request):
print(111)
if request.method == 'POST':
print(2222)
form = EditToBeSaveForm(request.POST)
if form.is_valid():
print(3333)
num = form.cleaned_data['病人编号']
new_p = Patient.objects.get(p_number=num)
if new_p:
print(4444)
new_p.p_name = form.cleaned_data['姓名']
new_p.p_sex = form.cleaned_data['性别']
new_p.p_age = form.cleaned_data['年龄']
new_p.p_tel_number = form.cleaned_data['电话号码']
new_p.save()
return render(request, 'polls/patient_edit.html')
else:
form = EditToBeSaveForm()
return render(request, 'polls/patient_num.html', {'form': form})
i can only see 111 in the shell output.it seems that the view even didn't receive the post request.and i check my html file and find the problem.the form's destination direct to another view function…… it's so stupid, i'm sorry for waste your time !
another django question. I have a edit form like this. Look at current_status in the code.
It has been updated:
def edit_item(request, client_id = 0, item_id = 0):
client = None
item = None
status = None
contact = None
status_id = request.POST.get('status_id', None)
contact_id = request.POST.get('contact_id', None)
save_item = request.POST.get('save_item', None)
save_status = request.POST.get('save_status', None)
try:
client = models.Client.objects.get(pk = client_id)
item = models.StorageItem.objects.get(pk = item_id)
except:
return HttpResponseNotFound()
try:
status = models.Status.objects.get(pk = status_id)
contact = models.Contact.objects.get(pk = contact_id)
except:
pass
if request.method == 'POST':
form = forms.ItemForm(request.POST, instance = item)
if form.is_valid() and save_item is not None:
form.save(True)
request.user.message_set.create(message = "Item {0} has been updated successfully.".format(item.tiptop_id))
return HttpResponse("<script language=\"javascript\" type=\"text/javascript\">window.opener.location = window.opener.location; window.close();</script>")
if status is not None and contact is not None and save_status is not None:
current_status = models.ItemStatusHistory(item = item, contact = contact, status = status,
user = request.user)
item.current_item_status_date = date.today()
item.save()
current_status.save()
request.user.message_set.create(message = "Item status has been updated successfully.")
else:
form = forms.ItemForm(instance = item)
title = str(client) + ' : Edit Item'
status_list = models.Status.objects.all()
return render_to_response('edit_item.html', {'form':form, 'title':title, 'status_list':status_list, 'item':item}, context_instance = RequestContext(request))
current_status save's the latest date of when the form is edited. What I ALSO want to do is to save this value into this models field.
class StorageItem(models.Model):
current_item_status_date = models.DateField()
Is ItemForm a ModelForm (see Django Model Forms)?
If so form.save() will return a model instance. Then you can edit its fields if you need to. For example.
my_obj = form.save()
my_obj.current_item_status_date = datetime.date.today()
my_obj.save()
If not, then simply create a new instance of your model and save the field value.
my_obj = StorageItem(current_item_status_date=datetime.date.today())
my_obj.save()