I'am trying to display data from the database file which has the value Age : 50 but
i alway get "Age object" displayed in the html. I'm very new too Django.
Here is the code
//base.HTML displays :
Age object
//base.html code :
<body>
{{ obj }}
</body>
//views.py :
def home(request):
obj = Age.objects.all()
return render_to_response("base.html",{'obj': obj})
//models.py
class Age(models.Model):
age = models.CharField(max_length=100)
simply obj is an array of objects, you have to print the attribute of the object.
If you want to show only one age(the first) you have to do:
//views.py :
def home(request):
obj = Age.objects.all()[0]
return render_to_response("base.html",{'obj': obj})
//base.html code :
<body>
{{ obj.age }}
</body>
You need to specify what field to show.
{{ obj.age }}
You need to either do obj.age in the template, or implement str or unicode method on your object that returns the age.
Related
I have some values that I collected from users in a form, which are saved to the DB. I want to take these values, perform an operation on them in function, and then return them so that I can use them in them alongside the other context.
Here is my model:
#models.py file
class MyModel(models.Model):
varA = models.PositiveIntegerField()
varB = models.PositiveIntegerField()
varC = models.PositiveIntegerField()
And here is the outside function that I am using:
#makecalc.py
def MakeCalc(varA, varB, varC):
#simplified from what I am actually doing
varD = varA*varB**varC
varE = varA+varB+varC
return varD, varE
And here is the views.py file:
#views.py file
from .makecalcs import MakeCalc
class MySummary(DetailView):
model = MyModel
def get_vars(self):
varD, varE = MakeCalc(varA, varB, varC) #Am I passing this correctly?
return varD, varE #How do I send these to context?
And finally the html:
<p> you input: {{ MyModel.varA }}</p>
<p> you input:{{ MyModel.varB }}</p>
<p> you input:{{ MyModel.varC }}</p>
<p> I output:{{ varD }}</p> #how do I call this?
<p> you input:{{ varE }}</p> #how do I call this?
So, my question is in the view, how do I add varD, varE to context so that I can use it alongside varA, varB, and varC from the model?
Add the get_context_data() method to your view, like this:
def get_context_data(self, **kwargs):
context = {}
context['your_custom_var'] = 'your_custom_value'
return super(MySummary, self).get_context_data(**context)
I am using django here is my model:
class Location(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=50)
altitude = models.IntegerField(max_length=10000)
area = models.ForeignKey('Area')
def __str__(self):
return str(self.area) + ':' + str(self.name)
#measurement.id value date location
class Measurement(models.Model):
id = models.IntegerField(primary_key=True)
value = models.FloatField(max_length=50)
data = models.DateTimeField()
location = models.ForeignKey('Location')
def __str__(self):
return "measurement#"+str(Location.objects.filter(id=self.id))
My HTML page is showing {'value__avg': 46.26524716693248} when it should just show 46.265.
Heres my function:
#property
def average_measurement(self):
locations = Location.objects.filter(area__name=self.name)
return Measurement.objects.filter(location__in=locations).aggregate(Avg('value'))
so how do I get the ugly part out?
aggregate() returns a dictionary where the key is combined from the grouping keys and grouping function name, you can just get the value by key:
return Measurement.objects.filter(location__in=locations).aggregate(Avg('value'))["value__avg"]
Or, if needed, you can also do that in the template using the dot-notation:
{{ obj.average_measurement.value__avg }}
You can also preset the key name with your own value:
return Measurement.objects.filter(location__in=locations).aggregate(my_average=Avg('value'))
Then, you would access it as:
{{ obj.average_measurement.my_average }}
That's not the ugly part, it's expected output and you need to understand what does the output mean. When you do django Aggregation, it returns a dictionary-like object with your aggregation criteria as keys and results as values.
What you need to do is to access it like a dictionary in template to extract the values:
{% for item in items %}
{{ item.value__avg|floatformat:3 }}
{% endfor %}
Check django doc about what is the lookup sequence for dot in template.
Also checkout django doc about aggreate function call.
Also checkout django doc about floatformat template filter.
I'm returning a record set from MongoDB, parsing this as JSON and pushing this into a view and attempting to access dictionary values of each record in a template. I can print the records (as an individual record), but I cannot access the structure of each record as a dictionary. How can I get at the values?
def index(request):
results = settings.vali_collection.find({'index': [] })
json_docs = [json.dumps(doc, default=json_util.default) for doc in results]
return render(request, 'db.html', {'results': json_docs[0:3]})
In my template:
{% for result in results %}
{{ result.name}}
{{ result.items.name}}
{% endfor %}
My JSON looks like:
{"name": "Travel & Leisure", .., ..}
I can print the records in my template with {{record}}, but how do I get at the record as a dictionary? What I have above in the template doesn't work and returns nothing. But when I use:
{% for result in results %}
{{ result}}
{% endfor %}
I can get the records printed out to screen in JSON format. If I print out json_docs I get the following:
['{"name": "random", "sector": "random"}', {"name": "random", "sector": "random"}', {"name": "random", "sector": "random"}']
If the json is a dictionary itself, you need to have nested loops. Something like the following:
{%for i in gme%}
{%for l, k in i.items%}
<p> {{l}} {{k}} </p>
{%endfor%}
{%endfor%}
gme looks like this:
gme = [{"sdfje": 'sdfs',"sdfds": "sdf"},...]
The output is:
sdfje sdfs
sdfds sdf
Use json.loads(...) instead of json.dumps.
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
Serialize obj to a JSON formatted str
json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
Deserialize s (a str or unicode instance containing a JSON document) to a Python object using this conversion table.
What you are doing is serializing python dictionary to JSON formatted str, so you get string instead of dictionary.
You need to deserialize and for that, you need json.loads
If you can't use json.loads, as you said in comments section, then the results variable is not a json string. Maybe it is what you are looking for? Try to debug and see what is inside results
If you're using PyMongo 2.8 find returns a Cursor that can be sliced. This should work:
db.test.find()[20:25]
And this should also work:
result = db.test.find()
...
sliced_result = result[20:25]
You don't need to transform the result to JSON, you can transform the Cursor to a list and pass that directly to the template, like that:
def index(request):
results = settings.vali_collection.find({'index': []})[:3]
return render(request, 'db.html', {'results': list(results)})
You need to use list(results) to force the Cursor to execute the query. In your template you'll have a list of dicts, so this should work:
{% for result in results %}
{{ result.name }}
{{ result.items.name }}
{% endfor %}
result should be a dict. The only problem I see is that items is a template function in Django, this might confuse people that are reading your template, and would prevent you from doing something like this:
{% for result in results %}
{% for attr_name, value in result.items %}
{{ attr_name }}: {{ value }}
{% endfor %}
{% endfor %}
The inner for would show every attribute, and their value, of a document in your MongoDB collection.
If you're using an older version of PyMongo that doesn't allow slicing, you may need to do something like this:
def index(request):
results = settings.vali_collection.find({'index': []}).limit(3)
return render(request, 'db.html', {'results': list(results)})
limit limits the number of results returned by the Cursor.
I believe result in the template isn't what you think it is. Let's examine as follows:
In function index(request):
results = settings.vali_collection.find({'index': [] }) returns a list of dictionary-like objects.
json_docs = [json.dumps(doc, default=json_util.default) for doc in results] returns a list of JSON strings (not dictionaries).
So later on when you iterate through the sublist json_docs[0:3], you are just iterating through a list of strings which is why you cannot reference the .name and .items properties.
It looks like what you actually want is a dict() like object for each result in your template. To do this, avoid dumping the dictionaries into JSON.
So instead of:
# WRONG:
json_docs = [json.dumps(doc, default=json_util.default) for doc in results]
return render(request, 'db.html', {'results': json_docs[0:3]})
# /WRONG
...just pass the result in directly:
results = settings.vali_collection.find({'index': [] })
results = list(results) # This may or may not be necessary, depending on what mongo client you're using
return render(request, 'db.html', {'results' : results[:3])
Then in your template, when you iterate through results, each result should be a dictionary-like object which you can use result.name or result.items on.
BTW, the result.items.name reference in your code looks a bit weird to me (like it would return an error), but it's hard for me to debug without knowing what each record looks like.
Change your view like this
def index(request):
results = settings.vali_collection.find({'index': [] })
return render(request, 'db.html', json.dumps({"results":results[0:3]}))
You can now use your for loop to render
I have a content that I'd like to rate on multiple criteria.
Imagine this kind of model:
class Content(models.Model):
name = models.CharField(max_length=50)
class Criterion(models.Model):
name = models.CharField(max_length=50)
content = models.ForeignKey(Content)
class ContRate(models.Model):
user = models.ForeignKey(User, help_text="Who rated ?")
crit = models.ForeignKey(Criterion)
rate = models.DecimalField()
The user has a page displaying the content.
From this page, he can also rate the content on the criteria set
The rating will be done with Ajax.
Now I'm trying to implement the view & the template
view.py
#...
def viewcont(request, content_id):
"""The user can view a content & rate it"""
content = get_object_or_404(Content, pk=content_id)
RateFormSet = modelformset_factory(ContRate)
formset = RateFormSet(queryset=ContRate.objects.filter(content=content, user=request.user))
objs = {
'content': content,
'forms': formset,
}
return render_to_response('content/content_detail.html', objs
, context_instance=RequestContext(request)
)
#...
content_detail.html
<!-- ... -->
<div id="rating">
<ul>
{% for crit in content.crit_set.all %}
<li>
{{ crit }}
<div class="rateit"
data-rateit-value="the_actual_rating_if_already_there"
data-rateit-ispreset="true"
crit-id="{{ crit.id }}"></div>
</li>
{% endfor %}
</ul>
</div>
<!-- ... -->
Now how can I use the forms formset to display the actual rates ?
And how can I draw an empty form to be posted by Ajax from any clicked star ?
(I know the javascript/jQuery part)
Not sure what the point of the formset is here. The rates are all available via the criteria object, using the reverse foreign key to ContRate in exactly the same way as you've done from Criteria to Content.
To make this as efficient as possible, you probably want to get the relevant ratings in the view and bring them together into a single datastructure:
content = get_object_or_404(Content, pk=content_id)
criteria = content.criteria_set.all()
user_ratings = ContRate.objects.filter(content=content, user=request.user)
ratings_dict = dict((c.crit_id, c.rate) for c in user_ratings)
for crit in criteria:
crit.user_rating = ratings_dict.get(crit.id)
Now you can pass criteria directly to your template, and there you can iterate through it to show the user_rating for each one.
(Final point: "criteria" is plural, the singular is "criterion". :-)
Let's say I have an string variable called *magic_string* which value is set to "This product name is {{ product.name }}" and it's avaible at django template. Is it ever possible to parse that variable to show me "This product name is Samsung GT-8500" instead (assuming that name of the product is "GT-8500" and variable {{ product.name }} is avaible at the same template) ?
I was trying to do something like this, but it doesn't work (honestly ? Im not surprised):
{{ magic_string|safe }}
Any ideas/suggestions about my problem ?
Write custom template tag and render that variable as a template.
For example look at how "ssi" tag is written.
On the other hand, can you render this string in your view? Anyway here is an untested version of that tag:
#register.tag
def render_string(parser, token):
bits = token.contents.split()
if len(bits) != 2:
raise TemplateSyntaxError("...")
return RenderStringNode(bits[1])
class RenderStringNode(Node):
def __init__(self, varname):
self.varname = varname
def render(self, context):
var = context.get(self.varname, "")
return Template(var).render(context)
Perhaps I dont understand your question but what about,
from django.template import Context, Template
>>> t = Template("This product name is {{ product.name }}")
>>> c = Context({"product.name": " Samsung GT-8500"})
>>> t.render(c)
Regards.