django render the same page after post - python

I am trying to create a form that gets JSON inputs through a textarea(textarea1) and then processes it and prints the response back in another text area(textarea2) while still showing the original json input from textarea1. I have the code that takes the input computes the result and puts the value back. But the values are not shown in the new form. My server does not use any models.
Here is the code from views.py
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
import simplejson
import read_json
from .forms import JsonTestForm
import sys
import traceback
def index(request):
form = JsonTestForm()
return render(request, 'ellora/index.html', {'form': form})
def get_json_text(request):
print "Enter method get_json_text"
if request.method == 'POST':
print "request method is post"
form = JsonTestForm(request.POST)
if form.is_valid():
print "form is valid"
#call the read_json.py and pass the json script in the appropriate format
# capture the result of it in some way and then redirect it to the results page
try:
data_string=form.cleaned_data['jsonText']
data = simplejson.loads(data_string)
#do some processing of the data here
f = open("temp/test7777777.py", "r")
form.cleaned_data['pythonScript'] = f.read()
return render(request, "ellora/index.html", {"form": form})
except Exception as e:
exc_type, exc_value, exc_traceback = sys.exc_info()
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
print ''.join('! ' + line for line in lines)
mystr = ''.join('! ' + line for line in lines)
form.cleaned_data['pythonScript'] = mystr
print "cleanded_data=", form.cleaned_data['pythonScript']
return render(request, "ellora/index.html", {"form": form})
else:
print "request type was not POST"
code from my forms.py
from django import forms
class JsonTestForm(forms.Form):
jsonText = forms.CharField(label="", widget=forms.Textarea(attrs={"class": "txtarea", "placeholder": "Enter your json script here"}), initial="[]")
pythonScript = forms.CharField(label="", widget=forms.Textarea(attrs={ "class": "txtarea", "readonly": "readonly", "rows": "1", "cols": ""}), initial="python script here")
testLog = forms.CharField(label="", widget=forms.Textarea(attrs={ "class": "txtarea", "readonly": "readonly", "rows": "1", "cols": ""}), initial="logs here")
Thanks for your help

You need to use AJAX. This should give you an idea of how to go about this. AngularJS would also allow you to easily do this, depending on the logic required.

Related

LayoutError at /invoice/ Flowable <PmlTable#0x1D09C899130 7 rows x 5 cols(tallest row 841)> with cell(0,0)

I am trying to print invoice in PDF format in Django I used xhtml2pdf to convert HTML doc. to PDF but when I try to run my code it gives me this error :
LayoutError at /invoice/ Flowable <PmlTable#0x1D09C899130 7 rows x 5 cols(tallest row 841)> with cell(0,0) containing '<PmlKeepInFrame at 0x1d09b77d670> size=x'(538.5826771653543 x 5893.228346456693), tallest cell 841.9 points, too large on page 2 in frame 'body'(538.5826771653543 x 785.19685039370
this is in my views.py
from django.http import HttpResponse
from django.views.generic import View
from booking.utils import render_to_pdf
from django.template.loader import get_template
class GeneratePDF(View):
def get(self, request, *args, **kwargs):
template = get_template('invoice.html')
context = {
"invoice_id": 1234,
"customer_name": "John Cooper",
"amount": 1399.99,
"today": "Today",
}
html = template.render(context)
pdf = render_to_pdf('invoice.html', context)
if pdf:
response = HttpResponse(pdf, content_type='application/pdf')
filename = "Invoice_%s.pdf" %("12341231")
content = "inline; filename='%s'" %(filename)
download = request.GET.get("download")
if download:
content = "attachment; filename='%s'" %(filename)
response['Content-Disposition'] = content
return response
return HttpResponse("Not found")
and this is my urls.py
from django.urls import path
from booking.views import GeneratePDF
app_name = 'booking'
urlpatterns = [
path('invoice/', GeneratePDF.as_view(), name ="invoice"),
]
I got the answer
xhtml2pdf is not able to split table cells that are larger than the available space. To work around it you may define what should happen in this case. The -pdf-keep-in-frame-mode can be one of: “error”, “overflow”, “shrink”, “truncate” where “shrink” is the default value.
table { -pdf-keep-in-frame-mode: shrink;}
documentation link

Gmail sending with currently generated pdf in Django

I am trying to send a pdf as a Gmail attachment in Django, which is just generated by the same view. For generating the pdf, I use to try this tutorial link.
my views.py:
def submit_report(request, pk):
template = get_template('app/pdf_rprt.html')
Industry_obj = Industry.objects.get(id=pk)
Industry_Report_obj = Industry_obj.industry_report_set.all()
report_tableA_obj = report_tableA.objects.filter(industry_report__industry=Industry_obj)
context = {
'industry' : Industry_obj,
'Industry_Report' : Industry_Report_obj,
'report_tableA' : report_tableA_obj,
}
html = template.render(context)
pdf = render_to_pdf('app/pdf_rprt.html', context)
if pdf:
to = "kanchon2199#gmail.com"
email = EmailMultiAlternatives(
#subject =
"final report sending (beta)",
#content =
'hello, this is test report sending mail',
#from email
settings.EMAIL_HOST_USER,
#list of recipent
[to]
)
email.attach_file(pdf)
email.send()
return redirect('app:index')
here the render_to_pdf comes from a custom build function in utils.py:
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
But it says error like (for the line email.attach_file(pdf)):
TypeError at /submit_report/1/
expected str, bytes or os.PathLike object, not HttpResponse
How can I fix it?
However, I have found a solution to this problem. the return type of render_to_pdf inside the utils.py should be ContentFile like this:
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
return ContentFile(result.getvalue(), 'sampleReport.pdf')
return None
and inside views.py the email.attach_file() need dir path inside it, so we can use our database to save the pdf file and then attach it like this:
def submit_report(request, pk):
template = get_template('app/pdf_rprt.html')
context = {
'industry' : Industry_obj,
'Industry_Report' : Industry_Report_obj,
'report_tableA' : report_tableA_obj,
}
html = template.render(context)
pdf = render_to_pdf('app/pdf_rprt.html', context)
if pdf:
Final_report_obj = Final_report.objects.create(pdf=this_pdf)
Final_report_obj.save()
to = [gmail1#gmail.com, gmail2#gmail.com.....]
email = EmailMultiAlternatives(
"your Subject",
"your content.... ",
settings.EMAIL_HOST_USER,
to
)
email.attach_file(os.path.join(settings.MEDIA_ROOT, Final_report_obj.pdf.name))
email.send()
return redirect('app:index')
Here I use the Final_report_obj named model just to store my pdf file, we can use another type of model also.

Django signal not working with django-paypal

I am trying to handle the signal valid_ipn_received from the package django-paypal (docs: https://django-paypal.readthedocs.io/en/stable/standard/ipn.html)
engine/signals.py
from paypal.standard.models import ST_PP_COMPLETED
from paypal.standard.ipn.signals import valid_ipn_received
from engine.models import DatasetRequest
from django.views.decorators.csrf import csrf_exempt
def show_me_the_money(sender, **kwargs):
print('test')
ipn_obj = sender
if ipn_obj.payment_status == ST_PP_COMPLETED:
# WARNING !
# Check that the receiver email is the same we previously
# set on the `business` field. (The user could tamper with
# that fields on the payment form before it goes to PayPal)
if ipn_obj.receiver_email != "paypalemail#gmail.com":
# Not a valid payment
return
# ALSO: for the same reason, you need to check the amount
# received, `custom` etc. are all what you expect or what
# is allowed.
if ipn_obj.mc_gross == ipn_obj.amount and ipn_obj.mc_currency == 'USD':
pk = ipn_obj.invoice
dsr = DatasetRequest.objects.get(pk=pk)
dsr.is_paid = True
dsr.save()
else:
pass
valid_ipn_received.connect(show_me_the_money)
engine/apps.py
from django.apps import AppConfig
class EngineConfig(AppConfig):
name = 'engine'
def ready(self):
import engine.signals
engine/views.py
def pay_for_dataset_request(request, dsr_pk):
# dsr_pk = dataset request primary key
dsr = DatasetRequest.objects.get(pk=dsr_pk)
paypal_dict = {
"business": "paypalemail#gmail.com",
"amount": dsr.reward,
"item_name": dsr.title,
"invoice": dsr.pk,
"notify_url": request.build_absolute_uri(reverse('paypal-ipn')),
"return": request.build_absolute_uri(reverse('datasetrequest_detail', kwargs={'pk': dsr.pk, 'slug': dsr.slug})),
"cancel_return": request.build_absolute_uri(reverse('datasetrequest_detail', kwargs={'pk': dsr.pk, 'slug': dsr.slug})),
}
# Create the instance.
form = PayPalPaymentsForm(initial=paypal_dict)
context = {"form": form}
return render(request, "payment.html", context)
"valid_ipn_received" is not firing when i make payments on 127.0.0.1:8000, nor ngrok, nor my production server. What is wrong with my code? I am new to signals.
Have you made sure that your apps.py file is actually being run? You can test by inserting breakpoint() or just a print() call.
You may need to add a line to your module's __init__.py like so:
default_app_config = 'app.engine.apps.EngineConfig'
or similar to make sure that it's loaded. See the documentation on AppConfigs.

How to render output of cartridge API's on custom HTML page?

I am working on a cartridge project. I have created custom html templates for better visual and now I want to render all data which is coming through cartridge's built in APIs on my custom html pages. For.ex. I have a product.html, on which I want to show all products stored in db (category wise).
Actually, I tried to explore url,
url("^shop/", include("cartridge.shop.urls")),
I am not getting that on which API or Function, this url is hitting.
urls.py file of shop app looks like this, I tested it, none of those url get called,
from __future__ import unicode_literals
from django.conf.urls import url
from mezzanine.conf import settings
from cartridge.shop import views
_slash = "/" if settings.APPEND_SLASH else ""
urlpatterns = [
url("^product/(?P<slug>.*)%s$" % _slash, views.product,
name="shop_product"),
url("^wishlist%s$" % _slash, views.wishlist, name="shop_wishlist"),
url("^cart%s$" % _slash, views.cart, name="shop_cart"),
url("^checkout%s$" % _slash, views.checkout_steps, name="shop_checkout"),
url("^checkout/complete%s$" % _slash, views.complete,
name="shop_complete"),
url("^invoice/(?P<order_id>\d+)%s$" % _slash, views.invoice,
name="shop_invoice"),
url("^invoice/(?P<order_id>\d+)/resend%s$" % _slash,
views.invoice_resend_email, name="shop_invoice_resend"),
]
These are cartridge's views for '/shop/product', '/shop/wishlist' and '/shop/cart'
from __future__ import unicode_literals
from future.builtins import int, str
from json import dumps
from django.contrib.auth.decorators import login_required
from django.contrib.messages import info
from django.core.urlresolvers import reverse
from django.db.models import Sum
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect
from django.template import RequestContext
from django.template.defaultfilters import slugify
from django.template.loader import get_template
from django.template.response import TemplateResponse
from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
from mezzanine.conf import settings
from mezzanine.utils.importing import import_dotted_path
from mezzanine.utils.views import set_cookie, paginate
from mezzanine.utils.urls import next_url
from cartridge.shop import checkout
from cartridge.shop.forms import (AddProductForm, CartItemFormSet,
DiscountForm, OrderForm)
from cartridge.shop.models import Product, ProductVariation, Order
from cartridge.shop.models import DiscountCode
from cartridge.shop.utils import recalculate_cart, sign
try:
from xhtml2pdf import pisa
except (ImportError, SyntaxError):
pisa = None
HAS_PDF = pisa is not None
# Set up checkout handlers.
handler = lambda s: import_dotted_path(s) if s else lambda *args: None
billship_handler = handler(settings.SHOP_HANDLER_BILLING_SHIPPING)
tax_handler = handler(settings.SHOP_HANDLER_TAX)
payment_handler = handler(settings.SHOP_HANDLER_PAYMENT)
order_handler = handler(settings.SHOP_HANDLER_ORDER)
def product(request, slug, template="shop/product.html",
form_class=AddProductForm, extra_context=None):
"""
Display a product - convert the product variations to JSON as well as
handling adding the product to either the cart or the wishlist.
"""
published_products = Product.objects.published(for_user=request.user)
product = get_object_or_404(published_products, slug=slug)
fields = [f.name for f in ProductVariation.option_fields()]
variations = product.variations.all()
variations_json = dumps([dict([(f, getattr(v, f))
for f in fields + ["sku", "image_id"]]) for v in variations])
to_cart = (request.method == "POST" and
request.POST.get("add_wishlist") is None)
initial_data = {}
if variations:
initial_data = dict([(f, getattr(variations[0], f)) for f in fields])
initial_data["quantity"] = 1
add_product_form = form_class(request.POST or None, product=product,
initial=initial_data, to_cart=to_cart)
if request.method == "POST":
if add_product_form.is_valid():
if to_cart:
quantity = add_product_form.cleaned_data["quantity"]
request.cart.add_item(add_product_form.variation, quantity)
recalculate_cart(request)
info(request, _("Item added to cart"))
return redirect("shop_cart")
else:
skus = request.wishlist
sku = add_product_form.variation.sku
if sku not in skus:
skus.append(sku)
info(request, _("Item added to wishlist"))
response = redirect("shop_wishlist")
set_cookie(response, "wishlist", ",".join(skus))
return response
related = []
if settings.SHOP_USE_RELATED_PRODUCTS:
related = product.related_products.published(for_user=request.user)
context = {
"product": product,
"editable_obj": product,
"images": product.images.all(),
"variations": variations,
"variations_json": variations_json,
"has_available_variations": any([v.has_price() for v in variations]),
"related_products": related,
"add_product_form": add_product_form
}
context.update(extra_context or {})
templates = [u"shop/%s.html" % str(product.slug), template]
return TemplateResponse(request, templates, context)
#never_cache
def wishlist(request, template="shop/wishlist.html",
form_class=AddProductForm, extra_context=None):
"""
Display the wishlist and handle removing items from the wishlist and
adding them to the cart.
"""
if not settings.SHOP_USE_WISHLIST:
raise Http404
skus = request.wishlist
error = None
if request.method == "POST":
to_cart = request.POST.get("add_cart")
add_product_form = form_class(request.POST or None,
to_cart=to_cart)
if to_cart:
if add_product_form.is_valid():
request.cart.add_item(add_product_form.variation, 1)
recalculate_cart(request)
message = _("Item added to cart")
url = "shop_cart"
else:
error = list(add_product_form.errors.values())[0]
else:
message = _("Item removed from wishlist")
url = "shop_wishlist"
sku = request.POST.get("sku")
if sku in skus:
skus.remove(sku)
if not error:
info(request, message)
response = redirect(url)
set_cookie(response, "wishlist", ",".join(skus))
return response
# Remove skus from the cookie that no longer exist.
published_products = Product.objects.published(for_user=request.user)
f = {"product__in": published_products, "sku__in": skus}
wishlist = ProductVariation.objects.filter(**f).select_related("product")
wishlist = sorted(wishlist, key=lambda v: skus.index(v.sku))
context = {"wishlist_items": wishlist, "error": error}
context.update(extra_context or {})
response = TemplateResponse(request, template, context)
if len(wishlist) < len(skus):
skus = [variation.sku for variation in wishlist]
set_cookie(response, "wishlist", ",".join(skus))
return response
#never_cache
def cart(request, template="shop/cart.html",
cart_formset_class=CartItemFormSet,
discount_form_class=DiscountForm,
extra_context=None):
"""
Display cart and handle removing items from the cart.
"""
cart_formset = cart_formset_class(instance=request.cart)
discount_form = discount_form_class(request, request.POST or None)
if request.method == "POST":
valid = True
if request.POST.get("update_cart"):
valid = request.cart.has_items()
if not valid:
# Session timed out.
info(request, _("Your cart has expired"))
else:
cart_formset = cart_formset_class(request.POST,
instance=request.cart)
valid = cart_formset.is_valid()
if valid:
cart_formset.save()
recalculate_cart(request)
info(request, _("Cart updated"))
else:
# Reset the cart formset so that the cart
# always indicates the correct quantities.
# The user is shown their invalid quantity
# via the error message, which we need to
# copy over to the new formset here.
errors = cart_formset._errors
cart_formset = cart_formset_class(instance=request.cart)
cart_formset._errors = errors
else:
valid = discount_form.is_valid()
if valid:
discount_form.set_discount()
# Potentially need to set shipping if a discount code
# was previously entered with free shipping, and then
# another was entered (replacing the old) without
# free shipping, *and* the user has already progressed
# to the final checkout step, which they'd go straight
# to when returning to checkout, bypassing billing and
# shipping details step where shipping is normally set.
recalculate_cart(request)
if valid:
return redirect("shop_cart")
context = {"cart_formset": cart_formset}
context.update(extra_context or {})
settings.use_editable()
if (settings.SHOP_DISCOUNT_FIELD_IN_CART and
DiscountCode.objects.active().exists()):
context["discount_form"] = discount_form
return TemplateResponse(request, template, context)
When you hit shop url, your application will try to use an empty url from your cartridge.shop.urls file. So basically when you would like to check which API / view is called, go to this file and look for something similar to this:
url(r'^$', 'your-view', name='your-view'),
ok after posting your second urls file you have following options:
you call:
/shop/wishlist/ - you are executing a view named wishlist
/shop/cart/ - you are executing a view named cart
/shop/checkout/complete/ - you are executing a view named complete
so just find your views.py file, and all those views are going to be there

I don't understand tests in Django, Can you help me please?

I am having a hard time with tests in Django and Python, for my final project I am making a forums website, but I don't really have any idea how or what my tests should be. Here is the views page from mysite file. Could someone please walk me through what I should test for besides if a user is logged in.
from django.core.urlresolvers import reverse
from settings import MEDIA_ROOT, MEDIA_URL
from django.shortcuts import redirect, render_to_response
from django.template import loader, Context, RequestContext
from mysite2.forum.models import *
def list_forums(request):
"""Main listing."""
forums = Forum.objects.all()
return render_to_response("forum/list_forums.html", {"forums":forums}, context_instance=RequestContext(request))
def mk_paginator(request, items, num_items):
"""Create and return a paginator."""
paginator = Paginator(items, num_items)
try: page = int(request.GET.get("page", '1'))
except ValueError: page = 1
try:
items = paginator.page(page)
except (InvalidPage, EmptyPage):
items = paginator.page(paginator.num_pages)
return items
def list_threads(request, forum_slug):
"""Listing of threads in a forum."""
threads = Thread.objects.filter(forum__slug=forum_slug).order_by("-created")
threads = mk_paginator(request, threads, 20)
template_data = {'threads': threads}
return render_to_response("forum/list_threads.html", template_data, context_instance=RequestContext(request))
def list_posts(request, forum_slug, thread_slug):
"""Listing of posts in a thread."""
posts = Post.objects.filter(thread__slug=thread_slug, thread__forum__slug=forum_slug).order_by("created")
posts = mk_paginator(request, posts, 15)
thread = Thread.objects.get(slug=thread_slug)
template_data = {'posts': posts, 'thread' : thread}
return render_to_response("forum/list_posts.html", template_data, context_instance=RequestContext(request))
def post(request, ptype, pk):
"""Display a post form."""
action = reverse("mysite2.forum.views.%s" % ptype, args=[pk])
if ptype == "new_thread":
title = "Start New Topic"
subject = ''
elif ptype == "reply":
title = "Reply"
subject = "Re: " + Thread.objects.get(pk=pk).title
template_data = {'action': action, 'title' : title, 'subject' : subject}
return render_to_response("forum/post.html", template_data, context_instance=RequestContext(request))
def new_thread(request, pk):
"""Start a new thread."""
p = request.POST
if p["subject"] and p["body"]:
forum = Forum.objects.get(pk=pk)
thread = Thread.objects.create(forum=forum, title=p["subject"], creator=request.user)
Post.objects.create(thread=thread, title=p["subject"], body=p["body"], creator=request.user)
return HttpResponseRedirect(reverse("dbe.forum.views.forum", args=[pk]))
def reply(request, pk):
"""Reply to a thread."""
p = request.POST
if p["body"]:
thread = Thread.objects.get(pk=pk)
post = Post.objects.create(thread=thread, title=p["subject"], body=p["body"],
creator=request.user)
return HttpResponseRedirect(reverse("dbe.forum.views.thread", args=[pk]) + "?page=last")
First read the Django testing documentation. You might also want to read this book. It's dated in some areas, but testing is still pretty much the same now as it was in 1.1.
It's a bit much of a topic to cover in an SO answer.
Well, you could test:
If you have the right number of pages for the objects you're paginating.
If the page you're viewing contains the right object range. If trying to access a page that doesn't exist returns the
appropriate error.
If your views for listing objects and object detail return the correct HTTP status code (200)
For starters. Hope that helps you out.

Categories