How to render JSON on client-side from Google App Engine Entity - python

I would much appreciate some help on rendering a JSON object on client-side from a Google App Engine entity.
Here is all of my relevant code:
def render_str(template, **params):
t = jinja_env.get_template(template)
return t.render(params)
class BlogHandler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
params['user'] = self.user
return render_str(template, **params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
class Post(ndb.Model):
subject = ndb.TextProperty(required = True)
created = ndb.DateTimeProperty(auto_now_add = True)
startdate = ndb.DateTimeProperty()
enddate = ndb.DateTimeProperty()
class PostPage(BlogHandler):
def get(self, post_id):
key = ndb.Key('Post', int(post_id), parent=blog_key())
post = key.get()
postdict = post.to_dict()
postdict['startdate'] = postdict['startdate'].isoformat()
self.render("permalink.html", postdict = postdict)
In my script tag on the template page, I include
<script>
var jsonobject = JSON.parse({{ postdict['startdate']}});
var jsonobject1 = new Date(jsonobject);
</script>
Am I on the right track here? I would like to ultimately use the datetime object on the client-side for some Jquery functions.
Any help in pointing me in the right direction would be much appreciated.

There are a number of problems with your code. First of all, once you convert post to a dictionary postdict, you can't reference the elements with the dot notation. You have to use a dictionary reference postdict['startdate'] to reference the startdate element.
Next, I use the isoformat() function when storing a date in JSON format:
postdict['startdate'] = postdict['startdate'].isoformat()
This makes it easier to convert to a Javascript Date object:
<script>
var jsonobject = JSON.parse({{ postdict.jsonobject}});
jsonobject[0].y = new Date(jsonobject[0].y);
</script>

Related

Django Admin- Dynamic child ModelChoiceField queryset on parent ModelChoiceField

This question have been asked many times. I went through many of them, and still couldn't find what i am looking for.
I am trying to load child ModelChoiceField data on parent ModelChoiceField selection in Django-Admin only
My code is as follows:
class AddressForm(forms.ModelForm):
name = forms.CharField(max_length=150)
city = forms.ModelChoiceField(queryset=City.objects.all(), required=False)
class Meta:
model = Address
fields = ['name', 'country', 'city']
def __init__(self, *args, **kwargs):
if 'instance' in kwargs:
address = kwargs['instance']
self.base_fields['name'].initial = address.name
country = self.get_country(*args, **kwargs)
self.base_fields['city'].queryset = country.cities if country else City.objects.none()
super().__init__(*args, **kwargs)
but it's not working on onChange event.
Here's one I did for cars. You can adapt it by replacing Car Make with country and Car Model with city
Within the form __init__
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['car_make'].empty_label = 'Make'
self.fields['car_model'].empty_label = 'Model'
initial = kwargs.get('initial', None)
try: self.fields['car_model'].queryset = CarModel.objects.filter(car_make=initial['car_make'])
except: self.fields['car_model'].queryset = CarModel.objects.none()
Ajax view
def load_models(request):
car_make_id = request.GET.get('car_make')
car_models = CarModel.objects.filter(car_make_id=car_make_id).order_by('name')
return render(request, 'leases/partials/car_model_dropdown_list_options.html', {'car_models': car_models})
Ajax url
path('ajax/load-models/', views.load_models, name="ajax_load_models"),
Javascript (using JQuery) in template
$("#id_car_make").change(function () {
var url = $("#searchForm").attr("data-models-url"); // get the url of the `load_cities` view
var carMakeId = $(this).val(); // get the selected country ID from the HTML input
$.ajax({ // initialize an AJAX request
url: url, // set the url of the request (= localhost:8000/hr/ajax/load-cities/)
data: {
'car_make': carMakeId // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
$("#id_car_model").html(data); // replace the contents of the city input with the data that came from the server
}
});
});

Cherrypy and content-type

I've got a cherrypy app and I'm trying to change response header Content-type. I'm trying to do that with cherrypy.response.header['Content-Type'] = 'text/plain'. Unfortunately I'm still getting 'text/html'. I want to have set one content type for ok request and another content type for error message. The only way how can I change content type is with my decorator. But this set type for the method and I need to change it. Do you know where could be a problem?
My config:
config = {
'/': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
'tools.response_headers.on': True,
'tools.response_headers.headers': [('Content-Type', 'text/html')],
}
}
def GET(self, id):
cherrypy.response.headers['Content-Type'] = 'application/x-download'
somecode
if res < None:
cherrypy.response.headers['Content-Type'] = 'text/plain'
cherrypy.response.status=404
GET._cp_config = {'response.stream': True}
def stream():
def decorate(func):
def wrapper(*args, **kwargs):
name = time.strftime("%Y%m%d-%H%M%S")
cherrypy.response.headers['Content-Type'] = 'application/x-download'
cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="' + name + '.txt"'
cherrypy.response.headers['Transfer-Encoding'] = 'chunked'
return func(*args, **kwargs)
return wrapper
return decorate
#cherrypy.expose
class Network:
#stream()
def GET(self, id):
source = my_generator()
for i in source:
if res < None:
cherrypy.response.headers['Content-Type'] = 'text/plain'
cherrypy.response.status=404
break
yield bytes(i)
GET._cp_config = {'response.stream': True}
Ok, there is more complex code, config of cherrypy is in the previous comment. I have a generator, which yields me some data and this is streaming that data in file to the client. I know, there are definitely better solutions. Imagine that in res variable there is result from saving to db. The problem is, that this completely ignores my settings in the if condition. It's still returning a file (empty one). The decorator is the only way how to set content type, that's why it's there

Google App Engine Python: Accessing the database object in another class

I will dive straight into the code of the application I'm developing using Google App Engine in Python:
import os
import webapp2
import jinja2
from google.appengine.ext import db
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape=True)
class Handler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
t = jinja_env.get_template(template)
return t.render(params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
class Users(db.Model):
name = db.StringProperty(required = True)
password = db.StringProperty(required = True)
email = db.EmailProperty(required = True)
address = db.PostalAddressProperty(required = True)
join_date = db.DateTimeProperty(auto_now_add = True)
dob = db.DateTimeProperty()
phone = db.PhoneNumberProperty()
class Orders(db.Model):
name = db.StringProperty(required = True)
email = db.EmailProperty(required = True)
address = db.PostalAddressProperty(required = True)
class MainPage(Handler):
def get(self):
self.render("home.html")
class Register(Handler):
def get(self):
self.render("signup-form.html")
def post(self):
name = self.request.get("username")
password = self.request.get("password")
verify = self.request.get("verify")
email = self.request.get("email")
address = self.request.get("address")
phone = self.request.get("phone")
a = Users(name = name, password = password, email = email, address = address, phone = phone)
a.put()
self.response.write("Registration successful!")
class MP(Handler):
def get(self):
self.render("mp.html")
def post(self):
self.render("order2.html")
class Order2Login(Handler, Register):
def get(self):
self.render("orderlogin.html")
def post(self):
old_usr = self.request.get("loginname")
old_pwd = self.request.get("loginpwd")
ans = a.filter("name =", old_usr).filter("password =", old_pwd)
if ans:
self.response.write("You are a registered member!")
else:
self.response.write("You are NOT registered.")
class Order2New(Handler):
def get(self):
self.response.write("New user yeah")
app = webapp2.WSGIApplication([('/', MainPage),
('/register', Register),
('/mp', MP),
('/order2new', Order2New),
('/order2login', Order2Login)], debug=True)
Now, in the Order2Login class, I needed to access the database object 'a' so that I can confirm whether a user is already a member of my website. Now, for that, I inherited the Register class in my Order2Login class, since the 'a' object was initially created in the Register class.
However, after running my application on my local machine, I get the following error:
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases Handler, Register
What seems to be the problem in my code?
Inheriting like that doesn't make any sense at all. Even apart from the metaclass problem, inheriting wouldn't make that variable available anyway, since it's a local variable. And in any case, these are two completely separate requests, so data does not persist between them.
But I have no idea why you think you need access to that variable in any case. The User object was persisted to the datastore: in the login view, you don't want to query a, which is a single instance and doesn't have a filter method anyway, you want to query the User class.

django - how to replace startElement in XML?

I'm trying to generate a custom HTML and I have a value I want to pass into xml.startElement (or root if you're thinking in generic terms). How do I go about doing this?
I'm currently using django rest framework a class view and a custom renderer -
This is the beginning of the renderer -
class TESTRenderer(renderers.BaseRenderer):
media_type = 'application/xml'
format = 'xml'
charset = 'utf-8'
def render(self, data, accepted_media_type=None, renderer_context=None):
"""
Renders *obj* into serialized XML.
"""
if data is None:
return ''
stream = StringIO()
xml = SimplerXMLGenerator(stream, self.charset)
xml.startDocument()
xml.startElement(header.data, {})
So as you can see I'm trying to pass a variable called header into the xml.startElement
Here's the view where that data lies -
class TestDetail(APIView):
permission_classes = (AllowAny,)
"""
Retrieve, update or delete a snippet instance.
"""
def get(self, request, pk, format=None):
jobmst_name = queryset1
nodmst_alias = queryset2
sysval_integer = queryset3
mst = queryset4
dtl = queryset5
dep = queryset6
trg = queryset7
name = str(jobmst_name)
master = str(nodmst_alias)
dbversion = str(sysval_integer)
header = 'job id="%s" name="%s" master="%s" dbversion="%s" xmlversion="1"' % (pk, name, master, dbversion)
jobmststring = JobmstSerializer(mst)
jobdtlstring = JobdtlSerializer(dtl)
jobdepstring = JobdepSerializer(dep, many=True)
trgjobstring = TrgjobSerializer(trg, many=True)
jobmst_serialized = {'jobmst': jobmststring.data}
jobdtl_serialized = {'jobdtl': jobdtlstring.data}
jobdep_serialized = [{'jobdep':item} for item in jobdepstring.data]
trgjob_serialized = [{'trgjob':item} for item in trgjobstring.data]
jobgroup = header, jobmst_serialized, jobdtl_serialized, jobdep_serialized, trgjob_serialized
return TestResponse(jobgroup)
The response it's using is here -
class TestResponse(HttpResponse):
"""
An HttpResponse that renders its content into XML.
"""
def __init__(self, data, **kwargs):
content = TESTRenderer().render(data)
kwargs['content_type'] = 'application/xml'
super(TestResponse, self).__init__(content, **kwargs)
Is there something I'm missing with the TestDetail where I should separate the header from the data?
maybe like this?
return TestResponse (header, jobgroup)
and then alter TestResponse to include?
def __init__(self, header, data, **kwargs):
I don't know python/django. but it seems the "Value" you are talking about are actually attributes you want to assign to the element node. I posted the same on your /r/django thread about this.

[gae]redirect only succeed after second time

I am building a simple wiki on GAE, i wanted to add a normal redirect to the handler when the content put to the datastore.but it doesnt work until i submit twice it redirect to the content page not the edit page itself.
Here is my handler code:
class BlogHandler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
params['user'] = self.user
t = jinja_env.get_template(template)
return t.render(params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
class WikiFront(BlogHandler):
def get(self, url):
#pages = WikiData.all()
pages = db.GqlQuery("SELECT * FROM WikiData")
found = False
content = ""
for page in pages:
if page.url == url:
found = True
content = page.content
if not found:
self.redirect("/_edit" + url )
else:
self.render('wiki.html', content=content, url=url)
class EditPage(BlogHandler):
def get(self,url):
if self.user:
self.render("wiki_edit.html")
else:
self.redirect("/login")
def post(self,url):
content = self.request.get('content')
if content:
w = WikiData(parent = wiki_key(), content = content, url= url)
w.put()
self.redirect('/wiki' + url )
else:
error = "Give us content plz"
self.render("wiki_edit.html", content=content, error=error)
# mapping stuff
app = webapp2.WSGIApplication([
('wiki' + PAGE_RE, WikiFront),
('/_edit' + PAGE_RE, EditPage),
],
debug=True)
If the redirect is happening after the Post method here, add a return statement after each redirect as it's more than likely trying to finish evaluating the method without completing the redirect.

Categories

Resources