So, Generic views are pretty cool, but what I'm interested in is something that's a generic template.
so for example, I can give it an object and it'll just tostring it for me.
or if I give it a list, it'll just iterate over the objects and tostring them as a ul (or tr, or whatever else it deems necessary).
for most uses you wouldn't need this. I just threw something together quickly for a friend (a bar stock app, if you must know), and I don't feel like writing templates.
If there's a django model for it, you can just stick to django.contrib.admin or django.contrib.databrowse. If not, then you might manage by skipping the django template altogether. example:
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
But of course you wanted to avoid even writing that much, so instead of doing html, we can use plain text and the pprint module:
from django.http import HttpResponse
import datetime
from pprint import pformat
def current_datetime(request):
now = datetime.datetime.now()
return HttpResponse(pformat(now), mimetype="text/plain")
edit: Hmm... this seems like something a view decorator should handle:
from django.http import HttpResponse
import datetime
import pprint
def prettyprint(fun):
return lambda request:HttpResponse(
pprint.pformat(fun(request)), mimetype="text/plain")
#prettyprint
def current_datetime(request):
return datetime.datetime.now()
I don't see you getting away from writing templates, especially if you would want to format it, even slightly.
However you can re-use basic templates, for e.g, create a generic object_list.html and object_detail.html
that will basically contain the information to loop over the object list and present it, and show the object detail. You could use these "Generic" templates across the entire app if need be.
Related
from django.http import HttpResponse
from .models import Destination
def index(request):
boards = Destination.objects.all()
boards_names = list()
for Destination in boards:
boards_names.append(Destination.destinationtext)
response_html = '<br>'.join(boards_names)
return HttpResponse(response_html)
I have written this code following just for practice of django framework but I am getting the following errors through pylint :
E1101:Class 'Destination' has no 'objects' member
E0601:Using variable 'Destination' before assignment
You have two different issues, and not just one as you say:
E1101:Class 'Destination' has no 'objects' member: Is a warning
that occurs because pylint doesn't know about our special Django variables. A pylint plugin like pylint-django might do the trick.
E0601:Using variable 'Destination' before assignment: In the for loop in your code you defined a variable called Destination. This is not only bad practice because python variables need to be in lowercase_underscore but it overrides the Destination class, and that's what is causing this error. You probably wanted to do something like this:
for d in boards:
# Or:
for destination in boards:
You wrote in your view:
for Destination in boards:
# ...
This means that Python sees Destination as a local variable, a local variable that you use before it is assigned.
You can rename the variable in the loop to solve the problem, but actually you can make it more elegant and faster here by using .values_list(..):
from django.http import HttpResponse
from .models import Destination
def index(request):
response_html = '<br>'.join(
Destination.objects.values_list('destinationtext', flat=True)
)
return HttpResponse(response_html)
Nevertheless, I'm still not convinced that this solves the matter, since the destinationtext could contain HTML, which then will mix up in the response. Usually it is better to use templates.
I've read in a book that you should avoid doing this:
from .views import *
What I am currently doing is the following:
from . import views
My first question is, if this is the same thing just written differently?
My second question is if I should import it this way above or should I import every view separately?
from .views import (DetailView, EditView, DeleteView,
ListView, AnotherView, OneMoreView)
I mean it is bad practice because you import everything, even if you do not use it. If you have helper functions in your views, it imports those as well. If you go with the second option you must use the prefix views. before any view function/class. This can be a nuisance, therefore you should just import each view you would like to use, then you can just call the view.
In my app, I have a model folder / package.
In that model folder, I generally have a whole bunch of import statements (most of them from SQLAlchemy, such as String, Integer, Session, etc.
I find myself writing the same import statements again and again for stuff like User, Blog, Article, Etc. and have become pretty sloppy at it.
Understanding that explicit is better than implicit and then going ahead and disregarding that, is there a way to do this once?
this probably isnt what you want but who knows
common_imports.py
from sqlalchemy import Model,String,...
in other scripts just do
from common_imports import *
[edit]
actually I came up with a really awful and hacky way to do what you want
a really hacky way to do it might be something like
\root_of_package
-main.py
\models
-__init__.py
-model1.py
-model2.py
then in models\__init__.py
from sqlalchemy import String,Integer,...
from glob import glob
Base = ...
for fname in glob("%s/*.py"%dirname(__file__)):
with open(fname) as f:
eval(f.read())
__all__ = locals()
then in models/model1.py
#just use all the imports/locals from __init__.py as if they already existed
#this will be hellish if you use an IDE that checks for errors for you
class Model1(Base):
id = Column(Integer,primary_key=True)
...
then in main.py
from models import Model1
I do this in one of my applications.
# approot/m.py
from models.model import String, Integer, Session, (etc)
# Otherwise blank!
Then in everything else:
import m
Then you can do m.String, m.Integer, m.Session and etc. This also means I can further encapsulate my code so that later when I write up user models I can just add to m.py
from models.user import User, Group, PermissionSet
and continue to access m.User, m.Group and etc.
I now receive a task, that is developing a native app on phone based on a web project. So I think the best way to communicate between server and client is using json.
Then I need all the response give me a result of json format. But now in the web project, almost every view use render_to_response like the following:
ctxt = RequestContext(request,*args)
return render_to_response('XXX.html',ctxt)
Then I want rewrite render_to_response like below, so I need not to change every one to a new function:
def render_to_response:
return new HttpResponse(simplejson.dumps(*args), mimetype='text/json'))
Obviously, I can change the source code in django, but it's not a practicable method. Because other project also need use it.
Or I can write a new module with the render_to_response function, and import this after
from django.shortcuts import render_to_response
But I am not sure if this is possible.
If this can work, I also need to add this import into every .py files which is still a huge work.
So I want a best way with the least changes to the whole project.
Try replacing the return you have with this
return HttpResponse(json.dumps(ctxt), content_type="application/json")
On a different note, you do not really need to return the context if the client requesting it doesn't need it. You might be better of return a simple message like "Success"
Another solution is to include django-annoying in your project and use the #ajax_request decorator on all your views which want to respond as json.
#ajax_request
def my_view(request):
news = News.objects.all()
news_titles = [entry.title for entry in news]
return {'news_titles': news_titles}
Refer example here - https://bitbucket.org/offline/django-annoying/wiki/Home
I am setting up an application using Flask based on a tutorial I found on the web. The problem I am having is so far it seems like I will have to write a lot of code for each view/route that I want to make so I am trying to devise a better system but I think I dug myself into a hole where I wrote too much code before really testing each step and since im not familiar with the framework im kindof lost.
so what I want is a base view class that will extract away some boilerplate stuff. Here is my attempt so far.
import jinja2
from jinja2 import Environment as Jinja2Environment
from webassets import Environment as AssetsEnvironment
from webassets.loaders import YAMLLoader
from webassets.ext.jinja2 import AssetsExtension
from flask import render_template
from app import app
class BaseView(object):
def __init__(self):
"init"
def get_jinja_env(self):
jinja_env = Jinja2Environment(loader=jinja2.FileSystemLoader('templates/'), extensions=[AssetsExtension])
return jinja_env
def get_asset_env(self):
asset_loader = webassets.YAMLLoader('conf/assets.yml')
asset_env = asset_loader.load_environment()
bundles = asset_loader.load_bundles()
[asset_env.register(name, bundle) for name, bundle in bundles.iteritems()]
return asset_env
def render_tmpl(self, tmpl_file, **context):
"Renders Jinja Template"
jinja_env = self.get_jinja_env
jinja_env.assets_environment = self.get_asset_env
template = jinja_env.get_template(tmpl_file)
return template.render(context)
Class that attempts to inherit from BaseView
from app.BaseView import BaseView
from app import app
class HelloView(BaseView):
#app.route('/')
def respond(self):
self.render_tmpl('hello.html')
My reasoning behind this is later I intend to extend some Jinja functionality such as caching and have some data be available for every view and template.
You will want to use the View classes included in flask already.
As they are very well explained there is not much I could explain here. Just read through the docs and I think you will see, what you will have to do (the flask docs are awesome.)
If you want to cache you also might want to have a look at Flask-Cache.
This doesn't quite answer your question entirely, but I thought it was worth mentioning anyway.
You can 'export' variables into the Jinja environment globals:
app.jinja_env.globals['data'] = ['One', 'Two', 'Three']
Once you've done this, all templates have access to the data variable and can operate on it as if it were passed in via kargs. You don't really need to go to the trouble of creating a whole new view class; you can just process it once and then make it available everywhere. It's handy for sidebars and login statuses and whatnot.