Print all properties of an App Engine Model - python

I'm trying to find a way to easily loop through a Google App Engine (Python) Model and to print out each property and the property name.
This is how I'm trying it, and after some research I realize I can't next variables in each other. Is there a way to do this with filters or a way to return all of the values of the properties of a Model?
Thanks
templateargs = {'properties':MyModel.properties(), 'user1':MyModelObj, 'user2':MyModelObj}
{% for property in properties %}
Property: {{property}}
User1: {{user1.{{property}}}}
User2: {{user2.{{property}}}}
{% endfor %}

Take a look at how this to_json method grabs all the property values on a Model instance, it should point you in the right direction.

After some more research I realized the proper way to do this was with gettattr. I used a filter along the lines of:
#register.filter
def mygetattr(obj, name):
return getattr(obj, name)
As suggested here

Try:
vars(user1)[property]
See Built-in Functions.html#vars for a short explanation of how vars returns a dictionary of the instance variables.

Related

Show only not None values in Django template

I have a Model with numerous attributes; in the template rendered by my DetailView I want to show only the attributes that are not None.
This can be easily done with an if template tag that checks if the value of the attribute is not None, tho I should add an if condition for every attribute in my model, and there's a lot of them.
I would like to iterate through all the attributes and if not None display them.
In pseudo code it would look like this:
{% for attribute in my_instance.all_attributes %}
{% if attribute.value is not None %}
{{attribute.value}}
I can get a tuple of concrete attributes both through the class or the instance:
cls._meta.concrete_fields
or
self._meta.concrete_fields
Now that I have the my_instance.all_attributes in my pseudo code example, I can iterate it but I don't know how to get the actual value of the instance's attribute.
EDIT:
.concrete_values returns an array of Field instances, it looks like this:
(<django.db.models.fields.BooleanField: gov>, <django.db.models.fields.BooleanField: in_group>, <django.db.models.fields.CharField: legal_class>,)
I can access the value of the name attribute of the Field instance using .name. Calling .name on the example above would return 'gov', 'in_group', 'legal_class'
The authors of Django went out of their way to make sure that the template language isn't used to do things like this! Their opinion as I understand it is that templates should do formatting, and Python should do program logic.
There are two ways around it. One is to create a structure that the template can iterate through, and pass it to the DetailView context. Something like
def get_context_data(self):
data = super().get_context_data(**kwargs)
fieldnames = [
x.name for x in self.object._meta.concrete_fields ]
display_fields = [
(name, getattr( self.object, name, None)) for name in fieldnames ]
display_fields = [ x for x in display_fields if x[1] is not None ]
data['display_fields'] = display_fields
return data
and in the template you can now do
{% for name,value in display_fields %}
You might prefer to code a list of names instead of using ._meta.concrete_fields because that lets you choose the order in which they appear. Or you could start with an ordered list and append anything that's in the _meta but not yet in your list (and delete anything that's in your list but not in _meta)
The other way is to use Jinja as the template engine for this view.

What is the right way of getting values from database in django?

I come from an PHP/SQL background, so the whole data access technique in django is a challenge to get my head around. So far in the djangobook, it has taught me to use a unicode function in models.py if i want to get a value from a database.
def __unicode__(self):
return self.name
Surely this is not how its meant to be done? Firstly, it only returns one column, and also if i wanted to access the table from some other function for another purpose, is the "name" column the only thing i can ever return? Its as if i can only ever return one column from the table - in this case i have chosen "name".
currently i am doing:
Publisher.objects.filter(name='test')
but here there is no way of altering what i want to be returned, its always down to the static unicode function back in models.py that has to be manually altered?
Surely there is a way of just running a python version query looking like
"SELECT name, firstname FROM users WHERE user_id = 1"
so basically, how would i write this query in python without having to use the stupid, limited unicode function? How would a production web app do it? Am i completely missing the concept here?
Thanks, and sorry for the badly explained question.
P.S would it be better to just use SQL in django? or is this bad practice?
Fields can simply be accessed using attribute access:
publisher = Publisher.objects.get(name='test')
print publisher.pk
print publisher.name
print publisher.some_other_field
Or, regarding your example
user = User.objects.get(pk=1)
print user.first_name
print user.last_name
And, in a template:
{{ user.first_name }}
The __unicode__ method is used to display a representation of an object. It is not used for generic field access.
Regarding your question, no, you shouldn't be using SQL here.

Django: avoiding multiple evaluations of the same expression in a template?

When passing an object called widget as part of the context to rendering a django template, I may have a method which is a bit expensive, but I want to display the result of it more than once.
Python:
class Widget:
def work(self):
# Do something expensive
Template
This is a widget, the result of whose work is {{widget.work}}. Do
you want to save {{widget.work}} or discard {{widget.work}}?
Clearly I could work around this by evaluating the method once in the view code, and then passing the result in, but this seems to couple the view and the template too much. Is there a way for the template author to stash values for re-use later in the template? I would like to do something like this:
{% work_result = widget.work %}
This is a widget, the result of whose
work is {{work_result}}. Do you want to save {{work_result}} or discard {{work_result}}?
Does such a construct exist in the django template language?
{% with %}
{% with work_result=widget.work %}
Look Django docs for more information

Is there a better way to iterate over tuples in a (Django) template in Google App Engine?

Basically, what I'm trying to do is to render os.environ in a template in Google App Engine. I believe the technology is (or is adapted from) the Django template engine version 0.96 (but correct me if I'm wrong).
I found this question suggesting that you could do:
{{ for key, value in environ}}
But when I try that, I get an error saying:
'for' statements with five words should end in 'reversed': for key, value in environ
I guess that question was concerning another version of Django?
By the way, the value of environ is set to os.environ.items() before rendering the template.
Anyway, I came up a key_value_pair class that I could use instead:
class key_value_pair:
def __init__(self, key, value):
self.key = key
self.value = value
def make_kvp(key, iter):
return key_value_pair(key, iter[key])
make_kvp is small "factory" method that I later use to set the environ template value like this:
map(lambda x : make_kvp(x, os.environ), os.environ)
When doing that everything works just fine, but since I'm a totally new to the technologies in play here, I just wanted to make sure that I'm not overseeing some obvious simpler solution.
Simply iterate over the sequence using a single name, then index the name to get at the individual elements.
Also, in template you should write like this:
{% for x in dic %}
{% endfor %}

Form Field API?

I am iterating through list of form fields. How do I identify the type of each field? For checkbox I can call field.is_checkbox...are there similar methods for lists, multiplechoicefields etc. ?
Thanks
Have a look at the class for each field on your form:
for f_name, f_type in my_form_instance.fields.items():
print "I am a ",type(f_type)
# or f_type.__class__
This will produce output similar to <class 'django.forms.fields.BooleanField'>.
You can get the name as a simple string, if you prefer that, with:
print type(f_type).__name__
# produces 'BooleanField'
Edit: Also be careful about the distinction between a field and a widget. There isn't a Checkbox field in Django, but only a CheckboxInput widget, which is the default for a BooleanField. Do you mean to look up the widget (which is very rendering specific), or the field (which has more of a relation to the data type and validation for that form field)? If the widget, you can get the widget type using:
f_type.widget
Hope that helps!
I am not sure if this is what you want, but if you want to know what kind of field it is going to end up being in the HTML, you can check it with this:
{% for field in form %}
{{ field.field.widget.input_type }}
{% endfor %}
widget.input_type will hold text, password, select, etc.
P.S. I did not know this until 5 seconds ago. #django irc.freenode.net always has good help.
Presuming you're using HTML here... Because it isn't very clear.
How about giving it an extra class.
And if you didn't know allready, the class attribute will recognise this:
class="hello there you"
as having 3 classes. The class 'hello', the class 'there', and the class 'you'.
So if they allready have a class, just add a space and your custom clasname.

Categories

Resources