I'm learning Flask Web Development book , and in Chapter 13 , it's about "comments for the blog post"
The route function of post is as below , the book said "when page = -1" , it will caculate how much comments totally , and to be divided "FLASKY_COMMENTS_PER_PAGE" , then it can know how many pages totally and decided which is the last page that you will go to.
But what confused me is that why the "(post.comments.count()" need to subtract 1 ???
i.e. If the comments quantity is 22 , then I added 1 comment
The caculation should be (23-1)//FLASKY_COMMENTS_PER_PAGE + 1 ???
I really don't know why I should subtract 1....
#main.route('/post/<int:id>')
def post(id):
post = Post.query.get_or_404(id)
form = CommentForm()
if form.validate_on_submit():
comment = Comment(body = form.body.data, post = post, author = current_user._get_current_object())
db.session.add(comment)
flash('Your comment has been published.')
return redirect(url_for('.post',id = post.id, page = -1))
page = request.args.get('page',1,type=int)
if page == -1:
page = (post.comments.count()-1)//current_app.config['FLASKY_COMMENTS_PER_PAGE']+1
pagination = post.comments.order_by(Comment.timestamp.asc()).paginate(
page,per_page = current_app.config['FLASKY_COMMENTS_PER_PAGE'],
error_out = False)
comments = pagination.items
return render_template('post.html',posts=[post],form = form,comments=comments,pagination = pagination)
Let's see this line:
page = (post.comments.count()-1)//current_app.config['FLASKY_COMMENTS_PER_PAGE']+1
let FLASKY_COMMENTS_PER_PAGE be 10. The page numbering starts from 1. Without the subtracting when there are 9 comments: 9//10 + 1 = 0 + 1 = 1 which is still good, but when you got 10 comments: 10//10 + 1 = 1 + 1 = 2. So you got 2 pages instead of 1. That's why you need to subtract 1 from the total comments.
Related
SUM(B.RefundedAmount) + SUM(CASE WHEN B.AccountTypeID = 2 AND B.TotalStake = B.TotalPayout THEN B.TotalPayout ELSE 0 END)
The following is the logic for SQL code that I need to convert into a new powerBI column/measure.
RefundedAmount, AccountTypeID, TotalStake and TotalPayout are all columns in the dataset. I'm struggling to wrap my head around the addition aspect along with the IF/CASE WHEN statement.
Does it only mean that IF (AccountTypeID = 2 AND TotalStake = TotalPayout) then we return RefundedAmount + TotalPayout, otherwise return 0?
The measure always returns at least RefundedAmount, but if AccountTypeID = 2 and TotalStake = TotalPayout then it returns the sum of RefundedAmount and TotalPayout.
The measure could be written in DAX as:
Measure :=
VAR _refund = SUM ( 'Table'[RefundedAmount] )
VAR _payout =
SUMX (
FILTER (
'Table' ,
'Table'[TotalPayout] = 'Table'[TotalStake]
&& 'Table'[AccountTypeID] = 2
),
'Table'[TotalPayout]
)
RETURN
_refund + _payout
I have written a code in python using sqlalchemy fetching data from MySQL. When the page is 1 (start is 0 and end is 10), everything works fine but when the page is 2 (start is 10 and end is 20), the db_salon and db_user_paymant is null.
I tried using join and joinedload but still it does not work.
def get_user_bookings(db: Session, user_id: int, page: int):
start = (page - 1) * 10
end = (page * 10)
db_user_bookings = db.query(DbBasketMain).options(
subqueryload("db_basket_services"), subqueryload("db_salon"),
subqueryload("db_user_payment")).filter(
DbBasketMain.user_id == user_id, DbBasketMain.salon_id != None).slice(
start, end).all()
for each_booking in db_user_bookings:
each_booking.salon_name = each_booking.db_salon.name
for each_service in each_booking.db_basket_services:
if (each_service.barber_id):
db_barber = get_barber_by_id(
db=db, barber_id=each_service.barber_id)
each_service.barber_name = db_barber.name + " " + db_barber.family
each_service.barber_image = get_barber_profile_image(
db=db, barber_id=each_service.barber_id)
return db_user_bookings
When using slice, It is a must to use order_by.
Changing to order_by(DbBasketMain.id).slice(start, end) solved the problem.
I'd like to increase/decrease upVote column value by 1 depending on isUpVote boolean value. I get this error when I try the code below. postID and upVote values are all integer.
MySQLdb._exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'upVote': 0}' - 1 WHERE postID = '2'' at line 1")
#app.route('/posts/upvote', methods=['GET', 'PATCH'])
def upvote_post():
if request.method == 'PATCH':
data = request.get_json()
print(data)
postID = data['postID']
isUpVote = data['isUpVote']
cur = mysql.connection.cursor()
cur.execute("SELECT upVote FROM posts WHERE postID = '{}'".format(postID))
current_upVote = cur.fetchone()
if isUpVote:
cur.execute("UPDATE posts SET upVote = '{0}' + 1 WHERE postID = '{1}'".format(current_upVote, postID))
else:
cur.execute("UPDATE posts SET upVote = '{0}' - 1 WHERE postID = '{1}'".format(current_upVote, postID))
How should I fix the error?
And I'd like to know if there's a simpler way to update the upVote value in one line without defining current_upVote variable.
You don't need the select Query at all, you can simple add or subtract 1 of the current value
#app.route('/posts/upvote', methods=['GET', 'PATCH'])
def upvote_post():
if request.method == 'PATCH':
data = request.get_json()
print(data)
postID = data['postID']
isUpVote = data['isUpVote']
cur = mysql.connection.cursor()
if isUpVote:
cur.execute("UPDATE posts SET upVote = upVote + 1 WHERE postID = '{0}'".format( postID))
else:
cur.execute("UPDATE posts SET upVote = upVote - 1 WHERE postID = '{0}'".format( postID))
current_upvote is a dictionary containing the row that you fetched. You need to extract the value from it.
You can also do the arithmetic in Python, then just do a single query to update.
You should use parameters rather than string formatting to substitute into queries.
cur.execute("SELECT upVote FROM posts WHERE postID = %s", (postID,))
current_upVote = cur.fetchone()
if isUpvote:
vote = current_upVote['upVote'] + 1
else:
vote = current_upVote['upVote'] - 1
cur.execute("UPDATE posts SET upVote = %s WHERE postID = %s", (vote, postID))
However, the best way to do it is nbk's answer. I only posted this to explain why your code didn't work, and also to show the proper use of parameters.
I have a Django 1.9 project implementing small chat app. All messages from a certain recipient are grouped into dialogs, so the models are defined as follows:
class Dialog(models.Model):
# Some fields
class Message(models.Model):
dialog = models.ForeignKey(Dialog, ...)
text = models.TextField()
is_read = models.BooleanField(default = False)
My goal is to render a template with a table that renders dialogs. And for each dialog in the table, I need to see
the number of unread messages and
the text of the last message.
To illustrate, consider mock-data below:
Input:
id dialog_id message is_read
1 1 Hello, sir false
2 1 My name is true
3 1 Jack true
4 2 This site false
5 2 is perfect false
6 2 Cheers false
Desired output:
dialog_id last_message_in_dialog unread_messages_count
1 Jack 1
2 Cheers 3
In pure mysql, I would write a query like this:
select
a.dialog_id,
text as last_message_in_dialog,
(select count(*) from message
where dialog_id = a.dialog_id and is_read = false) as unread_messages_count
from message a
where id in (select max(id) from message group by dialog_id)
In Django terms, I have the code below:
max_id_qs = Message.objects.\
values('dialog__id').\
annotate(max_id = Max('id'),).values('max_id')
qs = Message.objects.filter(id__in = max_id_qs).\
values('dialog__id', 'text')
This code serves well to fetch the last message in each dialog. However, the problem is that I can't figure out how to implement the subquery (select count(*) from message where dialog_id = a.dialog_id and is_read = false) in Django. Maybe my total approach with max_id_qsis wrong, and there's more elegant and clear way to implement the query in Django ORM?
I've spent an entire day trying to solve this issue. help me please !
This will work :-
allDistinctIdWithNotReadMsg =
Message.objects.filter(is_read=False).values('id').annotate(the_count=Count('is_read',distinct('id')))
for ids in allDistinctIdWithNotReadMsg:
lastMsg = Message.objects.filter(dialog_id=ids['id']).order_by("-id")[0]
for msg in lastMsg:
print ids['id'] ,msg.message,ids['the_count']
For a list query I want to show how many prices there are for a specific product on a specific site.
I have found a way to do this with RawSQL, something I had never ever had to do before. Am I overlooking something?
queryset = Price.objects.all()
site_annotations = {}
for site in Site.objects.all():
site_annotations['num_prices_{}'.format(site.name)] = RawSQL(
'SELECT COUNT(id) '
'FROM `product_siteprice` '
'WHERE `product_siteprice`.`price_id` = `product_price`.`id` '
'AND site_id=%s', [site.pk]
)
queryset = queryset.annotate(**site_annotations)
edit
My models look simplified like this:
class Site(Model):
name = models.CharField(_('display name'), max_length=50)
class Price(Model):
name = models.CharField()
class SitePrice(Model):
price = models.ForeignKey(Price)
site = models.ForeignKey(Site)
Now the table I want is:
Product | Nr of prices on Site A | Nr of prices on Site B |
--------|------------------------|------------------------|
Iphone | 6 | 3 |
Xperia | 42 | 66 |
And I want to sort and filter on the number of prices, so thats why I need the annotation.
NB The name Price is a bit misleading if you don't know the rest of context, in this context it can be seen more like a Product
From what I understand, you just need to filter the prices on the related site, then get the count of the number of objects.
Price.objects.filter(site_price__site_id=site.pk).count()
Although you may just want to remove the site price model and replace it with a many to many field
I think the query that you want would look something like this:
qs = SitePrice.objects.values('price_id', 'site_id').annotate(d_count=Count('id'))
And to get the table that you want, you’d format it into a dict with something like this:
from collections import defaultdict
values = defaultdict(dict)
for x in qs:
values[ x['price_id'] ][ x['site_id'] ] = x['d_count']
To print out this table, you would use:
price_ids = list(values.keys()) # you don’t need `list` for python 2
site_ids = set()
for x in values.values():
site_ids |= set(x.keys())
site_ids = list(site_ids)
site_ids.sort()
prices = dict(Price.objects.filter(id__in=price_ids).values_list('id', 'name'))
sites = dict(Site.objects.filter(id__in=site_ids).values_list('id', 'name'))
print(' ', end='') # for python 3
# print ' ', # for python 2
for x in site_ids:
print('%-8s ' % sites[x], end='')
print('')
for x, counts in values.items():
print('%-8s ' % prices[x], end='')
for site_id in site_ids:
d_count = counts.get(site_id, 0)
print('%-8s ' % d_count, end='')
print('')