I am learning django from MDN.And i was working on locallibrary.There i got one problem.
I want to send only books on author page but not all book,only current page's author book.
If url is
/author/1
then sent only book of author id 1, not all
In AuthorDetailView i tried context['books']=Book.objects.filter(author__exact=Author.id).
but it give error
**TypeError at /catalog/author/1**
**int() argument must be a string, a bytes-like object or a number, not 'DeferredAttribute'**
When i write context['books']=Book.objects.filter(author__exact=1)
then it send only authorid 1's book on all page.
on author/2.
so i want to send authorid 2's book on author/2. 3's book on author/3.
But not all books on everypage.
It doesn't make sense to send all objects when needed few.
{% for book in books%}
{% if author.id is book.author.id %}
<li>
{{ book.title }} ({{book.author}})
</li>
{% endif %}
This code do what i wanted but by sending all objects.
I hope you understand what i want.
Here is my models,views https://pastebin.com/yY6M5LUA
filter will send you a queryset not a objects, what you need to do is to get the objects corresponding to the need, for eg, Book.objects.filter(author__exact=Author.id)[0] will give you the first object from the queryset, so you get the object from here.
You are using a DetailView, so you already have the current author in the context. So there's actually no reason to do anything in the view - you can remove your get_context_data method. Instead, you can follow the reverse relationship in the template:
{% for book in author.book_set.all %}
{{ book.title }}
{% endfor %}
Related
I have Django model with CharFields 'flname1', 'date1', and 'time1'. My goal in my HTML is to have a {{ forloop }} that runs through only the 'date1' and 'time1' fields and displayed all of them. My Problem is that in my views file I can't find a way to create a python variable that only contains two of the three fields from one model. Ie tried a lot but what I'm trying to avoid is...
posts = DocPost.objects.all()
This puts all three fields into a variable and displays them in my for loop which I don't want. I've also tried a lot of work with filters and go things that other people on the internet had success with that didn't work for me like...
posts = DocPost.objects.filter('flname1').only('date1', 'time1')
This didn't work and didn't section off date1 and time1 and pack them away in a variable that I could loop through. Ive tried a lot more than this at this point to no prevail. Thank for any help.
There are two things you can do to only get certain fields in a query and iterate over them. The template for both is pretty much the same
First, you can use only() to generate a queryset where each object only has certain fields populated and all the rest are deferred
# View
context['posts'] = DocPost.objects.only('date1', 'time1')
# Template
{% for post in posts %}
{{ post.date1 }}
{{ post.time1 }}
{% endfor %}
Second, you can use values() to generate a queryset of dictionaries that only contain the fields specified
# View
context['posts'] = DocPost.objects.values('date1', 'time1')
# Template
{% for post in posts %}
{{ post.date1 }}
{{ post.time1 }}
{% endfor %}
I am working on a basic ecommerce website.I have created a superuser page in which I would like to see all the orders as well as the order details like customer who ordered, their address etc. These are my models.py:
class ShippingAddress(models.Model):
customer=models.ForeignKey(Customer,on_delete=models.SET_NULL,null=True)
order=models.ForeignKey(Order,on_delete=models.SET_NULL,null=True)
address=models.CharField(max_length=200,null=False)
email=models.EmailField(null=False)
class Customer(models.Model):
user=models.OneToOneField(MyUser,null=True,blank=True,on_delete=models.CASCADE)
email=models.CharField(max_length=100)
class Order(models.Model):
customer=models.ForeignKey(Customer,on_delete=models.SET_NULL,null=True,blank=True)
complete=models.BooleanField(default=False,null=True,blank=False)
class OrderItem(models.Model):
product=models.ForeignKey(Product,on_delete=models.SET_NULL,null=True)
order=models.ForeignKey(Order,on_delete=models.SET_NULL,null=True,)
And this is my views.py:
def superuser(request):
user=User.objects.all()
customer=Customer.objects.all()
order=Order.objects.filter(complete=True)
items=OrderItem.objects.all()
shipping=ShippingAddress.objects.all()
return render(request,"superuser.html",{'order':order,'items':items,'customer':customer,'shipping':shipping})
Currently in my template I am unable to iterate over the above context such that I can get all the orders and with the every order I can print their orderitems as well as shipping details as well as customer details. I tried in one way which was really in efficient that was to iterate over all orders then iterate over all orderitems and check if orderitem.order.id was equal to order.id . Please tell me what is the best method to pass the objects in context which are the most efficient for my need . And how to iterate over them in my template.
Thanks
How about this?
# view
from django.shortcuts import render
from .models import Order
def superuser(request):
orders = Order.objects.select_related('customer__user')
orders = orders.prefetch_related('shippingaddress_set')
orders = orders.prefetch_related('orderitem_set')
return render(request,"superuser.html",{'orders':orders})
You can of course chain the .select_related and .prefetch_related calls on the same lines, I've split them up here for increased readability. You can read about select_related and prefetch_related in the docs. You can now use the 'orders' QuerySet in a template like this:
<!--template-->
{% if orders %}
<ul>
{% for order in orders %}
<li>order id: {{order.id}}</li>
<li>customer name: {{order.customer.id}}</li>
<li>customer email: {{order.customer.email}}</li>
{% if order.shippingaddress_set.all %}
<li>Shipping addresses:
<ul>
{% for shipadd in order.shippingaddress_set.all %}
<li>shipping address: {{shipadd.address}}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% if order.orderitem_set.all %}
<li>Order items:
<ul>
{% for item in order.orderitem_set.all %}
<li>orderitem id: {{item.id}}</li>
{% endfor %}
</ul>
</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
Using Django Debug Toolbar and going to the page above, I'm informed that 3 SQL queries are made:
One fetches data from the 'order' table, doing a LEFT OUTER JOIN with the 'customers' table ON customer id.
One fetches data from the 'shippingaddress' table, with a WHERE clause specifying rows that have a 'order_id' IN (<list of all order id's>).
A similar query is made for the 'orderitem' table.
This way, Django preemptively fetches all the required data from the database, rather than e. g. doing another query for every iteration.
You might find it strange that I included a loop for the shipping addresses in the HTML template. This is however necessary, because the way you've set up your models, there is a many-to-one relationship from shipping addresses to orders. This doesn't make a lot of sense IMO, so you will probably want to redefine the ShippingAddress model's relationships to the other models.
If you want to use additional information related to each order, you can of course add more prefetch_related/select_related calls before putting the QuerySet in your context.
I've added a user profile page to my flask app. Everything is working except for one item:
I would like to display is the user's "Account created on" date. As I've added this functionality (and the logic to record a user's creation date upon registering) after some users have already been created, this column in certain user's tables will be empty.
I decided to work around this with a little humor by using a jinja2 if / else statement to check if the user has a user_created date or not.
If the user has a date, it will be displayed. If not, instead of a date it will replace it with 'since the dawn of time'.
The problem is my {% if user.user_created %} conditional logic seems to be pulling the sqlalchemy DateTime class type instead of None displaying as so:
Member since: <class 'sqlalchemy.sql.sqltypes.DateTime'>
If used this same pattern to check for the existence of other data without problems so I'm guessing it's related to this column containing db.Column(db.DateTime), but I'm not sure how to solve it.
Here is my Jinja template code:
<h1>User: {{ user.username }}</h1>
{% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
{% if user.user_created %}
<p>Member since: {{ user.user_created }}</p>
{% else %}
<p>Member since: The dawn of time</p>
{% endif %}
And here is the column from my sqlalchemy User model:
user_created = (db.DateTime)
Any help would be appreciated
Yep, after testing the realization in the comment above, that was in fact the issue.
I accidentally omitted the db.Column in my model. All is working now.
Using Django ~=1.11 and Python 3.6
I am a beginner! Every answer I've found online for my question is more advanced than what I'm looking for.
Here's my model:
class Byte(models.Model):
text = models.CharField(max_length=30)
def __str__(self):
return self.text
Here's my view:
def byte_list(request):
bytes = Byte.objects.order_by('text')
return render(request, 'cloudapp/byte_list.html', {'bytes': bytes})
Here's my template:
{% block content %}
<div class="total">
<h2>Total number of words and phrases entered: {{ byte.count }}</h2>
</div>
<hr>
{% for byte in bytes %}
<div class="byte">
<h2>{{ byte.text }}</h2>
</div>
{% endfor %}
{% endblock %}
This allows the creation "Byte" objects in the /admin, with only one field - a small text field. Right now, the template simply displays a list of all the objects created.
Question/Problem: I'd like to display the total number/count of objects that have been created for the Byte model. In the template, I have a tag {{ byte.count }} to display this.
I've tried using count() and Aggregation, but not sure how to work those into my model/view/template. I'm looking for the most simple and up-to-date way to accomplish this, whether it's using a method or #property in the model, or some type of query set in the view.
You've got a few different options... the most common ways to get the total number of model instances I have seen are:
my_total = len(Byte.objects.filter())
or, without having to run the full query:
my_total = Byte.objects.count()
Here's a link to the resource doc for 1.11: https://docs.djangoproject.com/en/1.11/topics/db/aggregation/#cheat-sheet
There's nothing wrong with Exprator's answer, but one alternative is to use the built in length template filter:
<h2>Total number of words and phrases entered: {{ bytes|length }}</h2>
If you're not planning to iterate over the bytes queryset you could also call count on it directly in the template:
<h2>Total number of words and phrases entered: {{ bytes.count }}</h2>
That will force a second database query, though, so only do that if you aren't otherwise causing bytes to be evaluated.
The decision of what to put in the view and what to do with template filters/no-arg methods is more a question of style than a hard and fast rule. Erring on the side of using the view is usually right, here it's simple enough that I might just do it in the template.
def byte_list(request):
byte= Byte.objects.count()
bytes = Byte.objects.order_by('text')
return render(request, 'cloudapp/byte_list.html', {'bytes': bytes,'byte':byte})
And in template
{{ byte }}
I have the following code in my template:
{% for req in user.requests_made_set.all %}
{% if not req.is_published %}
{{ req }}
{% endif %}
{% empty %}
No requests
{% endfor %}
If there are some requests but none has the is_published = True then how could I output a message (like "No requests") ?? I'd only like to use Django templates and not do it in my view!
Thanks
Even if this might be possible to achieve in the template, I (and probably many other people) would advise against it. To achieve this, you basically need to find out whether there are any objects in the database matching some criteria. That is certainly not something that belongs into a template.
Templates are intended to be used to define how stuff is displayed. The task you're solving is determining what stuff to display. This definitely belongs in a view and not a template.
If you want to avoid placing it in a view just because you want the information to appear on each page, regardless of the view, consider using a context processor which would add the required information to your template context automatically, or writing a template tag that would solve this for you.