how to add an error message to be displayed if the user tried to add an entry that is already on the table
forms.py
class AddCatForm(ModelForm):
class Meta:
model = Categories
fields = ['category_name']
labels = {
'category_name': ('إسم الفئة الجديدة')
}
error_messages = {
'category_name': {
'unique': ('الفئة موجودة بالفعل')
}
}
views.py
def add_cat(request):
if request.method == "POST":
form = AddCatForm(request.POST)
if form.is_valid():
model_instance = form.save(commit=False)
model_instance.save()
return redirect('/')
else:
form = AddCatForm()
return render(request, "add_cat.html", {'form': form})
When i add an entry that is already there , it just does nothing , i want it to view an error
You might be getting an error which you will not see because of your indentation. Amend it to:
def add_cat(request):
if request.method == "POST":
form = AddCatForm(request.POST)
if form.is_valid():
model_instance = form.save(commit=False)
model_instance.save()
return redirect('/')
else:
form = AddCatForm()
return render(request, "add_cat.html", {'form': form})
Related
I got this error in my functional view:
save() got an unexpected keyword argument 'commit'
I'm try to save one object in database. 'debtors' is Many to Many field in models.py.
forms.py
class ExpenseForm(forms.ModelForm):
class Meta:
model = Expense
fields = ('amount', 'text', 'debtors', 'date', 'time',)
widgets = {
'date': AdminDateWidget(),
'time': AdminTimeWidget(),
'debtors': forms.CheckboxSelectMultiple(),
}
views.py
def expenseformview(request, pk):
if request.method == 'POST':
form = Expense.objects.create(
expenser = request.user,
amount = request.POST.get('amount'),
text = request.POST.get('text'),
date = request.POST.get('date'),
time = request.POST.get('time'),
)
form.debtors.add(request.POST.get('debtors'))
formcoseshare = form.save(commit=False)
formcoseshare.save()
form.save_m2m()
return redirect('expense_detail', pk=pk, expenseid=form.id)
else:
form = ExpenseForm()
return render(request, 'financials/expense_form.html', {'form': form})
How can to solve this problem?
Your form is not an ExpenseForm, it is a model object Expense, hence commit=False makes no sense, and neither does .save_m2m():
from django.contrib.auth.decorators import login_required
#login_required
def expenseformview(request, pk):
if request.method == 'POST':
form = ExpenseForm(request.POST, request.FILES)
if form.is_valid():
form.instance.expenser = request.user
expense = form.save()
return redirect('expense_detail', pk=pk, expenseid=expense.pk)
else:
form = ExpenseForm()
return render(request, 'financials/expense_form.html', {'form': form})
It is however unclear to me what pk is doing here: you do not use it in any way.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
def createProject(request):
form = ProjectForm()
initial_data = {
'responsible':request.user.username
}
yonetici = Project(host=request.user)
if request.method == 'POST':
form = ProjectForm(request.POST, instance=yonetici,initial=initial_data)
if form.is_valid():
form.save()
return redirect('home')
context = {'form': form}
return render(request, 'base/project_form.html', context)
i tried many solutions but i couldnt make it work where am i doing wrong?
how do I not save the form data until the transaction is done which is in a different URL, if the shipping form and the payment options were to be in the same URL then there wouldn't be this problem but it's not so how do I go about this? thx!
views.py
def checkout(request):
if request.method == 'POST':
form = ShippingForm(request.POST)
if form.is_valid():
new_shipping = form.save(commit=False)
new_shipping.customer = customer
new_shipping.order = order
#how do I not save the data until the transaction is successful
new_shipping.save()
return redirect('store:checkout_shipping')
else:
form = ShippingForm()
else:
form = ShippingForm()
context = {"form": form}
return render(request, 'shop/checkout.html', context)
def checkout_payment(request):
return render(request, 'shop/checkout_payment.html', context)
urls.py
path('checkout', views.checkout, name="checkout"),
path('checkout_payment', views.checkout_payment, name="checkout_payment"),
forms.py
class ShippingForm(forms.ModelForm):
address_one = forms.CharField(max_length=200)
address_two = forms.CharField(max_length=200)
I think what might help is to use sessions. Django will store this temporary data using session cookies. Here's the idea:
from django.forms.models import model_to_dict
def checkout(request):
form = ShippingForm(request.POST or None)
if form.is_valid():
new_shipping = form.save(commit=False)
new_shipping.customer = customer
new_shipping.order = order
request.session['partial-data'] = model_to_dict(new_shipping)
return redirect('store:checkout_shipping')
context = {"form": form}
return render(request, 'shop/checkout.html', context)
def checkout_payment(request):
# I'm guessing here is where the rest of the data
# is to be filled in. The data of the previous view
# is already here stored in the cookie
full-form-data = request.session['partial-data']
full-form-data['extra-field-1'] = 'something'
full-form-data['extra-field-2'} = 'something else'
form = ShippingForm(full-form-data or None)
if form.is_valid():
form.save()
context = {
'form': form
}
return render(request, 'shop/checkout_payment.html', context)
I am trying to make a form but it is not showing me. Instead it is giving me error UnboundLocalError at /withdraw/ local variable 'form' referenced before assignment How to resolve this issue?
views.py
#login_required
def withdraw(request):
if request.method == 'POST':
form = Withdrawapayment(request.POST)
if form.is_valid():
form.save()
messages.success(request, f'Your request has been submitted.')
return redirect('balance')
context = {'form': form}
return render(request, 'nextone/withdraw.html', context)
models.py
class WithdrawPayment(models.Model):
payment = models.DecimalField(max_digits=100, decimal_places=2)
class Meta:
verbose_name_plural = 'Withdraw Payment'
forms.py
class Withdrawpayment(forms.ModelForm):
class Meta:
model = WithdrawPayment
fields = ['payment']
You are handling for POST request only so change your view like this:
#login_required
def withdraw(request):
if request.method == 'POST':
form = Withdrawapayment(request.POST)
if form.is_valid():
form.save()
messages.success(request, f'Your request has been submitted.')
return redirect('balance')
else:
form = Withdrawpayemnt()
context = {'form': form}
return render(request, 'nextone/withdraw.html', context)
I have created an invoice and items in it using Modelform and inlineforset_factory.
Now I am trying to create edit form, but I am getting MultiValueDictKeyError when I try to edit those inline fields. If I just create new inlineformsets I can edit Modelform just fine. After one hour of googling I am no closer to finding any solution.
maxItems = 20
ItemFormSet = inlineformset_factory(Invoice, Item, can_delete=True, extra=maxItems)
Creating of new invoice (working perfectly)
def new_invoice(request):
if request.method == "POST":
form = InvoiceForm(request.POST)
if form.is_valid():
invoice = form.save(commit=False)
item_formset = ItemFormSet(request.POST,instance=invoice)
if item_formset.is_valid():
invoice.dateCreated = datetime.datetime.now()
invoice.save()
item_formset.save()
return redirect('list/new0')
else:
form = InvoiceForm()
item_formset = ItemFormSet(instance=Invoice())
return render(request, "form.html", {"form": form, "item_formset": item_formset })
Editing invoice (MultiValueDictKeyError)
def edit_invoice(request, invoice_id):
invoicer = get_object_or_404(Invoice, pk=invoice_id)
if request.method == "POST":
form = InvoiceForm(request.POST, instance=invoicer)
if form.is_valid():
invoice = form.save(commit=False)
item_formset = ItemFormSet(request.POST,instance=invoice)
if item_formset.is_valid():
invoice.dateCreated = datetime.datetime.now()
invoice.save()
item_formset.save()
return redirect('list/new0')
else:
form = InvoiceForm(instance=invoicer)
item_formset = ItemFormSet(instance=invoicer)
return render(request, "form.html", {"form": form, "item_formset": item_formset })
You have two variables, invoicer and invoice that I assume are different instances of the same object. Try re-writing your edit view like this:
def edit_invoice(request, invoice_id):
invoice = get_object_or_404(Invoice, pk=invoice_id)
if request.method == 'POST':
form = InvoiceForm(request.POST, instance=invoice)
formset = ItemFormSet(request.POST, instance=invoice)
if form.is_valid() and formset.is_valid():
invoice = form.save()
invoice.dateCreated = datetime.datetime.now()
invoice.save()
formset.save()
return redirect('list/new0')
else:
form = InvoiceForm(instance=invoice)
formset = ItemFormSet(instance=invoice)
context = {
'form': form,
'formset': formset,
}
return render(request, 'form.html', context)
Let me know if that works for you.
Ok, so I've found that problem was not in the views.py nor in forms.py, but in template. Because I've built the template without using {{form.as_p/table/...}} The form had some extra inputs - DELETE,ID and foreignKey... after adding them to my for loop, everything works fine :)