[Hejes-devel] [923] - blog/index: redirect to index with no args if 0 articles found w/ specified tag or category
hejes-devel at nytud.hu
hejes-devel at nytud.hu
Thu Sep 5 15:46:19 CEST 2013
Revision: 923
Author: mihaltz
Date: 2013-09-05 15:46:19 +0200 (Thu, 05 Sep 2013)
Log Message:
-----------
- blog/index: redirect to index with no args if 0 articles found w/ specified tag or category
- blog/manage: added insert/update/delete callback functions to automatically manage table tags
- blog/manage: tags automatically converted to lower-case
- blog/feed.rss: alpha
Modified Paths:
--------------
trunk/misc/dbblog/test.py
trunk/web2py/applications/helyesiras_webdev/controllers/blog.py
trunk/web2py/applications/helyesiras_webdev/models/dbblog.py
Modified: trunk/misc/dbblog/test.py
===================================================================
--- trunk/misc/dbblog/test.py 2013-09-03 09:33:37 UTC (rev 922)
+++ trunk/misc/dbblog/test.py 2013-09-05 13:46:19 UTC (rev 923)
@@ -18,6 +18,7 @@
sys.path.append('/opt/web2py')
from gluon import *
from gluon.dal import Row
+from gluon.validators import Validator
sys.path.append('../../web2py/applications/helyesiras_webdev/modules')
import util
@@ -63,7 +64,12 @@
dbblog.posts.body.requires = IS_NOT_EMPTY()
dbblog.posts.slug.requires = IS_NOT_EMPTY()
dbblog.posts.category.requires = IS_IN_DB(dbblog, dbblog.categories.id, '%(name)s')
- # TODO: posts.image_url.requires = IS_URL?
+ dbblog.posts.tags.requires = IS_LIST_OF(IS_LOWER())
+
+ dbblog.posts._after_update.append( _on_update_posts)
+ dbblog.posts._after_insert.append( _on_insert_posts)
+ dbblog.posts._after_delete.append( _on_delete_posts)
+ dbblog.posts._before_update.append( _bef_upd)
dbblog.commit()
@@ -82,10 +88,10 @@
def create_indexes():
"""Create indexes (if they didn't exist) on frequently used columns. Note: tables must already exist (otherwise raises exception)."""
- create_index_if_not_exists(db, 'images', 'idx_images_title', 'title', True)
- create_index_if_not_exists(db, 'tags', 'idx_tags_name', 'name', True)
- create_index_if_not_exists(db, 'categories', 'idx_categories_name', 'name', True)
- create_index_if_not_exists(db, 'posts', 'idx_posts_created_on', 'created_on')
+ create_index_if_not_exists(dbblog, 'images', 'idx_images_title', 'title', True)
+ create_index_if_not_exists(dbblog, 'tags', 'idx_tags_name', 'name', True)
+ create_index_if_not_exists(dbblog, 'categories', 'idx_categories_name', 'name', True)
+ create_index_if_not_exists(dbblog, 'posts', 'idx_posts_created_on', 'created_on')
dbblog.commit()
@@ -96,7 +102,7 @@
def add_test_data():
- dbblog.categories.bulk_insert([{'name': 'Hírek'}, {'name': 'Közönségszolgálat'}, {'name': 'Helyesírási érdekességek'}])
+ #dbblog.categories.bulk_insert([{'name': 'Hírek'}, {'name': 'Közönségszolgálat'}, {'name': 'Helyesírási érdekességek'}])
now = datetime.datetime.now()
dbblog.posts.insert(
slug='elindult-a-blog',
@@ -184,7 +190,103 @@
posts = dbblog(dbblog.posts.tags.contains(tag)).select(dbblog.posts.ALL)
print(posts)
+def test_set():
+ s = dbblog(dbblog.tags.id == 1289)
+ print(s)
+ print(s.query)
+ print(type(s.query))
+ print(s.query.as_dict())
+ print(s.query.as_json())
+ print(s.query.second)
+def _bef_upd(s, f):
+ print('before update: {0}, {1}'.format(s,f))
+ #print(s.select()[0].id)
+ #print(f['title'])
+
+def _aft_upd(s, f):
+ print('after update: {0}, {1}'.format(s,f))
+ print(s.query)
+
+def _on_update_posts(s, f):
+ """Callback functions on update operations on table posts in order to maintain table tags.
+ s: Set object, records updated, f: dictionary, field names and values passed to update
+ """
+ #print('after update: {0}, {1}'.format(s, f))
+ dbblog.executesql('LOCK TABLES tags WRITE, posts READ;') # prevent other sessions from accessing while we're doing maintenance
+ id = long(s.query.second) # s.select(dbblog.posts.id).first().id # id of post just updated
+ # 1. check whether each new tag is referred to from table tags
+ for tag in f['tags']: # tags just assigned to post
+ r = dbblog(dbblog.tags.name == tag).select() # get matching record from table tags
+ if len(r) == 1: # matching record exists:
+ if id not in r[0].posts: # check if contains reference to post, if not, update it
+ dbblog(dbblog.tags.name == tag).update(posts = r[0].posts + [id])
+ elif len(r) == 0: # no matching record: insert it
+ dbblog.tags.insert(name=tag, posts=[id])
+ #else: error!!! (more than 1 record exists with name==tag)
+ # 2. for each record in table tags that refers to post: check if post still has tag, if not, delete reference/record
+ to_delete = [] # ids of records that have to be deleted from table tags
+ for row in dbblog(dbblog.tags.posts.contains(id)).select():
+ if row.name not in f['tags']:
+ if len(row.posts) > 1:
+ dbblog(dbblog.tags.id == rid).update(posts = [x for x in row.posts if x != id]) # remove reference to post in question
+ else:
+ to_delete.append(row.id) # schedule for deleting
+ for rid in to_delete: # delete
+ dbblog(dbblog.tags.id == rid).delete()
+ dbblog.commit()
+ dbblog.executesql('UNLOCK TABLES;') # remove lock
+
+
+def _on_insert_posts(f, id):
+ """Callback functions on insert operations on table posts in order to maintain table tags.
+ f: a dict of fields passed to insert, id: the id of the newly inserted record
+ """
+ print('after insert: {0}, {1}'.format(f, id))
+ #dbblog.executesql('LOCK TABLES tags WRITE, posts READ;') # prevent other sessions from accessing
+ # Add each tag to table tags
+ for tag in f['tags']:
+ r = dbblog(dbblog.tags.name == tag).select() # get matching record from table tags
+ if len(r) == 1: # matching record exists: update it
+ dbblog(dbblog.tags.name == tag).update(posts = r.first().posts + [id])
+ elif len(r) == 0: # no matching record: insert it
+ dbblog.tags.insert(name=tag, posts=[id])
+ dbblog.commit()
+ dbblog.executesql('UNLOCK TABLES;') # remove lock
+
+
+def _on_delete_posts(s):
+ """Callback functions on insert operations on table posts in order to maintain table tags.
+ s: Set object, records deleted
+ """
+ print('after delete: {0}'.format(s))
+ #dbblog.executesql('LOCK TABLES tags WRITE, posts READ;') # prevent other sessions from accessing while we're doing maintenance
+ id = long(s.query.second) # id of post just deleted (gluon.DAL uses <Set (table.id = id)> for delete/update)
+ print('id of post just deleted: {0}'.format(id))
+ # Delete references from matching records in table tags or delete matching records that only referenced this post
+ to_delete = [] # ids of records that have to be deleted from table tags
+ for row in dbblog(dbblog.tags.posts.contains(id)).select():
+ if len(row.posts) > 1:
+ print('update tags set posts={0} where id={1}'.format([x for x in row.posts if x != id], row.id))
+ dbblog(dbblog.tags.id == row.id).update(posts = [x for x in row.posts if x != id]) # remove reference to post in question
+ dbblog.commit()
+ else:
+ to_delete.append(row.id) # schedule for deleting
+ for rid in to_delete: # delete
+ dbblog(dbblog.tags.id == rid).delete()
+ dbblog.commit()
+ dbblog.executesql('UNLOCK TABLES;') # remove lock
+
+def test_callbacks():
+ #dbblog.posts._before_update.append(lambda s,f: print('before update: {0}, {1}'.format(s,f)))
+ #dbblog.posts._before_update.append( _bef_upd)
+ #dbblog(dbblog.posts.id==1).update(tags=['új verzió'])
+ #dbblog.posts.insert(title='proba', tags=['teszt', 'ablak'])
+ #dbblog(dbblog.posts.id==9).delete()
+ dbblog(dbblog.posts.id==1).update(tags=['új verzió'])
+ #dbblog.commit()
+
+
#########
# main
#########
@@ -193,7 +295,10 @@
define_tables()
#create_indexes()
#add_test_data()
-regenerate_tags_table()
+#regenerate_tags_table()
+#test_set()
+#test_callbacks()
+test_validator()
#query_categories()
#query_posts()
Modified: trunk/web2py/applications/helyesiras_webdev/controllers/blog.py
===================================================================
--- trunk/web2py/applications/helyesiras_webdev/controllers/blog.py 2013-09-03 09:33:37 UTC (rev 922)
+++ trunk/web2py/applications/helyesiras_webdev/controllers/blog.py 2013-09-05 13:46:19 UTC (rev 923)
@@ -34,6 +34,8 @@
# prepare pagination
rset = dbblog(query)
ntotal = rset.count()
+ if ntotal == 0: # 0 articles found: redirect to index page with no args
+ redirect(URL(c='blog', f='index'))
perpage = 5
npages = (ntotal / perpage) + (1 if ntotal % perpage > 0 else 0)
tmp = safeint(request.vars.get('page'))
@@ -73,6 +75,22 @@
"""Show an SQLFORM.smartgrid to manage dbblog.posts
"""
grid = SQLFORM.grid(dbblog.posts, orderby=~dbblog.posts.created_on)
- #grid = SQLFORM.grid(dbblog.posts, left=dbblog.tags.on(dbblog.tags.posts.contains(dbblog.posts.id)))
- #grid = SQLFORM.smartgrid(dbblog.posts, linked_tables=['tags'])
return dict(grid=grid)
+
+
+def feed():
+ """Return a dict that can be rendered by views/generic.rss as the RSS feed of the blog. URL is .../blog/feed.rss"""
+ entries = []
+ posts = dbblog(dbblog.posts.category == dbblog.categories.id).select(orderby=~dbblog.posts.created_on, limitby=(0, 15))
+ for row in posts:
+ post = row.posts
+ entries.append(dict(title='Cim',# post.title,
+ link=URL(c='blog', f='show', args=[post.slug], host=True),
+ description='Leiras', #MARKMIN(post.body.split('\n')[0]).xml(),
+ created_on=str(post.created_on)
+ ))
+ return dict(title="Helyesiras.mta.hu blog",
+ link="http://helyesiras.mta.hu/helyesiras/blog",
+ description="A helyesiras.mta.hu oldal hivatalos blogja",
+ entries=entries)
+
Modified: trunk/web2py/applications/helyesiras_webdev/models/dbblog.py
===================================================================
--- trunk/web2py/applications/helyesiras_webdev/models/dbblog.py 2013-09-03 09:33:37 UTC (rev 922)
+++ trunk/web2py/applications/helyesiras_webdev/models/dbblog.py 2013-09-05 13:46:19 UTC (rev 923)
@@ -19,10 +19,80 @@
return True
+def _on_update_posts(s, f):
+ """Callback functions on update operations on table posts in order to maintain table tags.
+ s: Set object, records updated, f: dictionary, field names and values passed to update
+ """
+ #print('after update: {0}, {1}'.format(s, f))
+ dbblog.executesql('LOCK TABLES tags WRITE, posts READ;') # prevent other sessions from accessing while we're doing maintenance
+ id = long(s.query.second) # s.select(dbblog.posts.id).first().id # id of post just updated
+ # 1. check whether each new tag is referred to from table tags
+ for tag in f['tags']: # tags just assigned to post
+ r = dbblog(dbblog.tags.name == tag).select() # get matching record from table tags
+ if len(r) == 1: # matching record exists:
+ if id not in r[0].posts: # check if contains reference to post, if not, update it
+ dbblog(dbblog.tags.name == tag).update(posts = r[0].posts + [id])
+ elif len(r) == 0: # no matching record: insert it
+ dbblog.tags.insert(name=tag, posts=[id])
+ #else: error!!! (more than 1 record exists with name==tag)
+ # 2. for each record in table tags that refers to post: check if post still has tag, if not, delete reference/record
+ to_delete = [] # ids of records that have to be deleted from table tags
+ for row in dbblog(dbblog.tags.posts.contains(id)).select():
+ if row.name not in f['tags']:
+ if len(row.posts) > 1:
+ dbblog(dbblog.tags.id == rid).update(posts = [x for x in row.posts if x != id]) # remove reference to post in question
+ else:
+ to_delete.append(row.id) # schedule for deleting
+ for rid in to_delete: # delete
+ dbblog(dbblog.tags.id == rid).delete()
+ dbblog.commit()
+ dbblog.executesql('UNLOCK TABLES;') # remove lock
+
+
+def _on_insert_posts(f, id):
+ """Callback functions on insert operations on table posts in order to maintain table tags.
+ f: a dict of fields passed to insert, id: the id of the newly inserted record
+ """
+ print('after insert: {0}, {1}'.format(f, id))
+ #dbblog.executesql('LOCK TABLES tags WRITE, posts READ;') # prevent other sessions from accessing
+ # Add each tag to table tags
+ for tag in f['tags']:
+ r = dbblog(dbblog.tags.name == tag).select() # get matching record from table tags
+ if len(r) == 1: # matching record exists: update it
+ dbblog(dbblog.tags.name == tag).update(posts = r.first().posts + [id])
+ elif len(r) == 0: # no matching record: insert it
+ dbblog.tags.insert(name=tag, posts=[id])
+ dbblog.commit()
+ dbblog.executesql('UNLOCK TABLES;') # remove lock
+
+
+def _on_delete_posts(s):
+ """Callback functions on insert operations on table posts in order to maintain table tags.
+ s: Set object, records deleted
+ """
+ print('after delete: {0}'.format(s))
+ #dbblog.executesql('LOCK TABLES tags WRITE, posts READ;') # prevent other sessions from accessing while we're doing maintenance
+ id = long(s.query.second) # id of post just deleted (gluon.DAL uses <Set (table.id = id)> for delete/update)
+ print('id of post just deleted: {0}'.format(id))
+ # Delete references from matching records in table tags or delete matching records that only referenced this post
+ to_delete = [] # ids of records that have to be deleted from table tags
+ for row in dbblog(dbblog.tags.posts.contains(id)).select():
+ if len(row.posts) > 1:
+ print('update tags set posts={0} where id={1}'.format([x for x in row.posts if x != id], row.id))
+ dbblog(dbblog.tags.id == row.id).update(posts = [x for x in row.posts if x != id]) # remove reference to post in question
+ dbblog.commit()
+ else:
+ to_delete.append(row.id) # schedule for deleting
+ for rid in to_delete: # delete
+ dbblog(dbblog.tags.id == rid).delete()
+ dbblog.commit()
+ dbblog.executesql('UNLOCK TABLES;') # remove lock
+
+# -----------------------------------------------
+
# Connection to the database (admin)
dbblog = DAL("mysql://dbblogadmin:d4bl0GGr@localhost/dbhelyesblog")
-
# Define the table names and the fields + add restrictions.
dbblog.define_table('images',
Field('file', 'upload'),
@@ -58,11 +128,19 @@
dbblog.posts.body.requires = IS_NOT_EMPTY()
dbblog.posts.slug.requires = IS_NOT_EMPTY()
dbblog.posts.category.requires = IS_IN_DB(dbblog, dbblog.categories.id, '%(name)s')
+dbblog.posts.tags.requires = IS_LIST_OF(IS_LOWER())
-dbblog.commit()
-
# Create indexes (indices?) (if they didn't exist)
create_index_if_not_exists(dbblog, 'images', 'idx_images_title', 'title', True)
create_index_if_not_exists(dbblog, 'tags', 'idx_tags_name', 'name', True)
create_index_if_not_exists(dbblog, 'categories', 'idx_categories_name', 'name', True)
create_index_if_not_exists(dbblog, 'posts', 'idx_posts_created_on', 'created_on')
+
+# Set callbacks on table posts to automatically maintain table tags
+dbblog.posts._after_update.append( _on_update_posts)
+dbblog.posts._after_insert.append( _on_insert_posts)
+dbblog.posts._after_delete.append( _on_delete_posts)
+
+# make sure everything gets thru (?)
+dbblog.commit()
+
More information about the Hejes-devel
mailing list