I have this TemplateView:
class DamageEntry(TemplateView):
template_name = "damage/damageadd.html"
def get(self, request):
general = General.objects.get(pk=1)
form = DamageEntryForm()
args = {'form': form,
'general': general,
}
return render(request, self.template_name, args)
def post(self, request):
general = General.objects.get(pk=1)
form = DamageEntryForm(request.POST)
form.non_field_errors()
if form.is_valid():
post = form.save(commit=False)
if self.request.user.is_authenticated():
post.user = request.user
post.userip = get_client_ip(request) # το IP του χρήστη
location = get_cocation(post.lat, post.lng)
post.location = location
post.formatted_address= location.formatted_address
post.entry_date = datetime.datetime.now(tz=timezone.utc)
post.save()
form = DamageEntryForm()
args = {'form': form,
'general': general
}
return http.HttpResponseRedirect('damage/add/')
else:
print('form is not valid')
print(form.errors)
# form = DamageEntryForm()
args = {'form': form,
'general': general
}
return render(request, self.template_name, args)
It works fine for create new record.
I want to use thw same view for update, because of the extra code on Post section.
I use this URL for update:
# /damage/damage/list/1
url(r'damage/list/(?P<pk>[0-9]+)/$', views.DamageEntry.as_view(), name="damage-by-id"),
Can I do this? How can I pass pk for create and update record?
Related
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 have 2 views, display_quote and quoteline_update
After updating a quoteline, I want to redirect to display_quote (quote to which the quoteline updated belongs).
I obtain the error:
Reverse for 'display_quote' with no arguments not found. 1 pattern(s) tried: ['\\^display_quote/\\(\\?P(?P<pk>[^/]+)\\\\d\\+\\)\\$$']
Exception Type:NoReverseMatch
Views:
def display_quote(request, pk):
items_quote = Quote.objects.filter(pk=pk)
items_quote_line = LineQuote.objects.all().filter(num_quote_id=pk)
form = QuoteLineForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.save()
total = 0
for item in items_quote_line:
total = total + item.get_price()
context = {'items_quote': items_quote,
'items_quote_line': items_quote_line,
'form': form,
'total':total
}
return render(request, 'quote/quote_display.html', context)
def quoteline_update(request, pk):
model = QuoteLine
cls = LigneDevisForm
item = get_object_or_404(model, id=pk)
if request.method == "POST":
form = cls(request.POST, instance=item)
if form.is_valid():
form.save()
return redirect('display_quote')
else:
form = cls(instance=item)
return render(request, 'quote/quoteline_update.html', {'form': form})
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 :)
I am having trouble defining the URLs for my django app.
I want it so that when I type,
http://example.com/post/3 :: I can read a post
http://example.com/post/3/edit :: I can edit a post
At the moment, I defined it like the following:
url(r'^post/(?P<id>\d+)/edit/$',
'board.views.edit_post',
name='edit_post'),
url(r'^post/(?P<id>\d+)',
'board.views.view_post',
name='view_post'),
However this does not seem to work because when I click on my "edit" link which links to
"/post/{{ post.id }}/edit"
I get the intended url in my address bar but am not taken to the edit view...
===================================
--EDIT--
#login_required
def edit_post(request, id):
if id:
post = get_object_or_404(Post, id=id)
if post.owner_user != request.user:
return HttpResponseForbidden()
# else:
# post = Post(owner_user=request.user)
if request.POST:
form = PostEditForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('')
else:
form = PostEditForm()
return (request,'edit_post.html', {
'form': form})
And
def view_post(request, id):
#context = RequestContext(request)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.owner = request.user
form.parent_post = get_object_or_404(Post, id=id)
form.comment_type = 0
form.save()
return HttpResponseRedirect('')
else:
form = CommentForm()
return render(request,'view_post.html', {
#'comment' : get_object_or_404(Comment, parent_post = id),
'comment': Comment.objects.filter(parent_post=id),
'form': form,
'post': get_object_or_404(Post, id=id)
})
Well, I'll recommend you begin using Class Based Views, besides, why not. Can make your life easier, most times, whiles you write less
class UpdatePost(UpdateView):
model = Post # assuming you've made from your_app.models import Post call already
fields = ['title', 'content', 'pub_date'] # for demonstration purposes
template_name = 'post_form.html'
#method_decorator(login_required) #Use login required on your dispatch method
def dispatch(self, request, *args, **kwargs):
pulled = Post.objects.get(id=kwargs['id'])
if pulled.created_by == request.user: #just to verify person making edit is rightly disposed to do so
return super(UpdatePost, self).dispatch(request, *args, **kwargs)
raise PermissionDenied
Sweetly intercept the id in your url like so
url(r'^app/edit/(?P<id>\d+)/$', views.UpdatePost.as_view(), name='edit'),
That's how I do mine. I pulled this from my working project github.com/seanmavley/menpha.git, but haven't tested this tweaked version. But It should work.