Django Query Count Records on Row - python

I'm a little rusty with django.
I'm wondering if anyone can tell me how I count the db objects from this query:
UserEnteredTld = Tld.objects.filter(FKtoClient=request.user, auth=0)
I used to do:
UserEnteredTld = Tld.objects.filter(FKtoClient=request.user, auth=0).count()
In the template (with the var):
{% if UserEnteredTld %}
<h3>I have Tld's</h3>
{% endif %}
the view:
UserEnteredTld = Tld.objects.filter(FKtoClient=request.user, auth=0).count()
UserAuthTld = Tld.objects.filter(FKtoClient=request.user,auth=1).count()
return render(request, 'accounthome.html', {
'UserEnteredTld':UserEnteredTld,
'UserAuthTld':UserAuthTld
})
model
class Tld(models.Model):
auth = models.BooleanField(default=False)
FKtoClient = models.ForeignKey(User)
but, this appears to not be outputting anything. (I verified actual rows exist...)
To be clear: I'm simply trying to count the number of rows for the Tld table where a ForeignKey exists for the logged in user and the auth=0.

Don't use count for that. Use exists (docs).
user_entered_tld = Tld.objects.filter(FKtoClient=request.user, auth=False).exists()
{% if user_entered_tld %}
<h3>I have Tld's</h3>
{% endif %}
Some notes:
Django latest version is 1.7 (on beta). It's impossible you're using 2.6.2 (that seems like a Python version)
Don't camel-case your variables. Use user_entered_tld instead of
UserEnteredTld. It's a good Python convention.

Related

Optimise django manytomany relation

I was wondering if there is a way to make this more optimised.
class AppTopic(models.Model):
topic = models.CharField(max_length=20) # lowercase (cookies)
class UserTopic(models.Model):
topic = models.CharField(max_length=20) # Any case (cOoKiEs)
app_topic = models.ForeignKey(AppTopic) # related to (cookies -> lowercase version of cOoKiEs)
class User(models.Model):
topics = models.ManyToManyField(UserTopic) # AppTopic stored with any case
The goal is to have all AppTopics be lowercase on the lowest level, but I want to allow users to chose what capitalisation they want. In doing so I still want to keep the relation with it's lowercase version. The topic on the lowest level could be cookies, the user might pick cOoKiEs which should still be related to the orignal cookies.
My current solution works, but requires an entirely new table with almost no use. I will continue using this if there isn't really a smarter way to do it.
There's nothing in the Django model API that would allow you to manipulate values from the models themselves. If you don't want to change the value in the database or in the model instance, you can change how it displays on the template level using the
lower filter in Django template language.
<body>
<div>
{% if condition %}
<h1>{{AppTopic|lower}}</h1>
{% else %}
<h1>{{AppTopic|??}}</h1> #AppTopic but camelcase. There's no camelcase filter in Django
{% endif %}
</div>
</body
Views.py
def View(request, condition)
...
return render(request, 'template.html', {condition:'condition'})

How to query in django one to many

What I want to do?
I have an app have three models:Series,Section and Episode,every one have a one-many query(by ForeignKey). just like this
series-> many Section,section-> many Episode
Now I will show a section with episodes information in series page, but it make more query.
now code
views.py
series = Series.objects.get(id=series_id)
section = Section.objects.filter(series=series)
list.html
{% for item in sections %}
...
{% for episode in item.episode_set.all %}
...
{% endfor %}
...
{%endfor%}
models.py
class Section(models.Model):
series = models.ForeignKey(Series)
....
class Episode(models.Model):
section = models.ForeignKey(Section)
What I want to get ?
an example code tell me how to query in views.py and use just little query.
you can guess, in my code, if here are many section and many episode, it will have many query.
Some idea.
I use Laravel Before, In Laravel , it has a hasMany Function, I can use it to get other models items(Define by belongsTo).
Is Django has same function?
If in template you need only episodes, you can query just them with single query
Episode.objects.filter(section__series=series_id)
But if you need all data then you can use prefetch_related Django docs.
The simplest example looks enough for your code
series = Series.objects.filter(id=series_id).prefetch_related('section_set', 'section_set__episode_set').get()
After this calls to series.section_set.all() and to section.episode_set.all() will not produce extra query.

Django performance with render_to_response

I have Django app, which have following statements:
response = render_to_response('template.html', {'s':s, 'r':r}, context_instance=RequestContext(request))
The typical statement at template.html is:
<tbody>{%for m in r.m_set.all %}<tr>
<td>{{m.id}}</td>
<td>{{m.Name}}</td>
<td>{{m.MaterialLot.id}}</td>
<td>{{m.MaterialSublot.id}}</td>
<td>{{m.Description|truncatechars:20}}</td>
<td>{{m.StorageLocation.id}} - {{m.StorageLocation.Name}}</td>
<td>{{m.Quantity|floatformat:"-3"}}</td>
<td>{{m.QuantityUnitOfMeasure.id}}</td>
<td>{{m.Status.id}}</td></tr> {%endfor%}</tbody>
There are about 10 thousands records. the page response time take about 3 minutes(ThinkServer, Linux, Apache, mod_wsgi, Python3.4, Django 1.9.4, MySQL), is this normal?
Thanks!
Every call to {{ m.XXX.id }} leads to separate SQL-query for the XXX instance. To avoid this you should use the select_related() method of the queryset.
Add the following method to the class of the r variable:
def get_all_m(self):
return self.m_set.all().select_related()
and then use it in the template:
{% for m in r.get_all_m %}
To only access the id of the related models, add the _id suffix to the field name. This data is already available because that's the value of the foreign key, so you don't need extra queries or joins. However, you are accessing the Name property of the StorageLocation field, so you need a join to prevent doing a query in every iteration.
Your call for the data becomes:
r.m_set.select_related('StorageLocation').all()
Your template becomes:
<tbody>
{%for m in r.m_set.all %}
<tr>
<td>{{m.id}}</td>
<td>{{m.Name}}</td>
<td>{{m.MaterialLot_id}}</td>
<td>{{m.MaterialSublot_id}}</td>
<td>{{m.Description|truncatechars:20}}</td>
<td>{{m.StorageLocation.id}} - {{m.StorageLocation.Name}}</td>
<td>{{m.Quantity|floatformat:"-3"}}</td>
<td>{{m.QuantityUnitOfMeasure_id}}</td>
<td>{{m.Status_id}}</td>
</tr>
{%endfor%}
</tbody>
Just remember that if you need access to a field other than id on a related model, add the field name to the select_related() call.

Django pass render_to_response template in other template

this is probably a question for absolute beginners since i'm fairly new to progrmaming. I've searched for couple of hours for an adequate solution, i don't know what else to do.
Following problem. I want to have a view that displays. e.g. the 5 latest entries & 5 newest to my database (just an example)
#views.py
import core.models as coremodels
class LandingView(TemplateView):
template_name = "base/index.html"
def index_filtered(request):
last_ones = coremodels.Startup.objects.all().order_by('-id')[:5]
first_ones = coremodels.Startup.objects.all().order_by('id')[:5]
return render_to_response("base/index.html",
{'last_ones': last_ones, 'first_ones' : first_ones})
Index.html shows the HTML content but not the content of the loop
#index.html
<div class="col-md-6">
<p> Chosen Items negative:</p>
{% for startup in last_ones %}
<li><p>{{ startup.title }}</p></li>
{% endfor %}
</div>
<div class="col-md-6">
<p> Chosen Items positive:</p>
{% for startup in first_ones %}
<li><p>{{ startup.title }}</p></li>
{% endfor %}
Here my problem:
How can I get the for loop to render the specific content?
I think Django show render_to_response in template comes very close to my problem, but i don't see a valid solution there.
Thank you for your help.
Chris
--
I edited my code and problem description based on the solutions provided in this thread
the call render_to_response("base/showlatest.html"... renders base/showlatest.html, not index.html.
The view responsible for rendering index.html should pass all data (last_ones and first_ones) to it.
Once you have included the template into index.html
{% include /base/showlatest.html %}
Change the view above (or create a new one or modify the existing, changing urls.py accordingly) to pass the data to it
return render_to_response("index.html",
{'last_ones': last_ones, 'first_ones' : first_ones})
The concept is that the view renders a certain template (index.html), which becomes the html page returned to the client browser.
That one is the template that should receive a certain context (data), so that it can include other reusable pieces (e.g. showlatest.html) and render them correctly.
The include command just copies the content of the specified template (showlatest.html) within the present one (index.html), as if it were typed in and part of it.
So you need to call render_to_response and pass it your data (last_ones and first_ones) in every view that is responsible for rendering a template that includes showlatest.html
Sorry for the twisted wording, some things are easier done than explained.
:)
UPDATE
Your last edit clarified you are using CBV's (Class Based Views).
Then your view should be something along the line:
class LandingView(TemplateView):
template_name = "base/index.html"
def get_context_data(self, **kwargs):
context = super(LandingView, self).get_context_data(**kwargs)
context['last_ones'] = coremodels.Startup.objects.all().order_by('-id')[:5]
context['first_ones'] = coremodels.Startup.objects.all().order_by('id')[:5]
return context
Note: personally I would avoid relying on the id set by the DB to order the records.
Instead, if you can alter the model, add a field to mark when it was created. For example
class Startup(models.Model):
...
created_on = models.DateTimeField(auto_now_add=True, editable=False)
then in your view the query can become
def get_context_data(self, **kwargs):
context = super(LandingView, self).get_context_data(**kwargs)
qs = coremodels.Startup.objects.all().order_by('created_on')
context['first_ones'] = qs[:5]
context['last_ones'] = qs[-5:]
return context

get_absolute_url in django-categories

I would like to know this method must be to work up due to I've tried to implement but I could not.
Actually I've tried entering to the shell through
python manage.py shell
c=Category.objects.get(pk = 3)
c.get_absolute_url
#I got <bound method Category.get_absolute_url of <Category: Category2>>
c.get_absolute_url()
#It Doesn't work
I want to implement it within another model named Article that it's a foreign key to Category model
My intention is to have a method in Article like
def get_abs_url(self):
c=Category.objects.get(pk=self.category)
return c.get_absolute_url() + '/' + self.slug
Something like that
Perhaps you could supply more information regarding your models and what you are trying to achieve. Something like this might help:
models.py
class Article(models.Model):
category = models.ForeignKey(Category, related_name='article')
...
Where ever you return a queryset in views:
def get_context_data(self, **kwargs):
context = super(ArticleView, self).get_context_data(**kwargs)
context['articles'] = Article.objects.all().select_related('category')
return context
In templates:
{% for article in articles %}
{% for category in article.category %}
{{ category.get_absolute_url }}/{{ category.slug }} # this will return a string: abs_url/slug
{% endfor %}
{% endfor %}
Read about select_related here: https://docs.djangoproject.com/en/dev/ref/models/querysets/#select-related
You could also take a look at implementing Managers: https://docs.djangoproject.com/en/dev/topics/db/managers/#django.db.models.Manager
Finally, I overcame this problems throw the follow solution, first of all, my intention have always been to get something like that
/c/slug_category_parent/slug_first_children/.../last_children.
I've resolved throw this solution in settings.py:
cat_url= lambda c: cat_url(c.parent) + '/' +c.slug if c.parent else '/c/'+ c.sl
ABSOLUTE_URL_OVERRIDES = {
'categories.category': lambda c: cat_url(c),
}

Categories