EDIT MODE

Rebrickable is under constant change. To keep you up to date it is time for another admin news article. The period between these can vary depending on the amount of news we have to bring. The blogs are all tagged so you can easily find others in the series.

Rules Reminder - Scraping

Scraping is where people use automated tools to harvest data from websites intended for human interactions. As per the Terms of Service, scraping of Rebrickable pages is not allowed. This is not a new rule, but Nathan has recently improved bot detection and enforcing this more than in the past.

Why is this important?

MOC designers trust us to protect their data. As the largest MOC marketplace we are often targeted by theives, or people wanting to train AI, or others with less than honourable intentions. This is why the majority of data relating the MOCs is not avaliable via the API or download files. This is also why you now need to be logged in when downloading free instructions.

But I'm making an app that needs this data!

Rebrickable does offer a large amount of the data on the website both via an API and via download files. Things like set info, part numbers and relationships, etc are free to use, even for commercial purposes. However we do recommend giving credit to where the data came from. If your project relies on data not avaliable via these methods, you can create a suggestion on the forums for this to be introduced, but be prepared that the answer may be privacy issues prevent us from sharing it.

New Help Pages

Rebrickable has some new help pages!

Tips for Creating MOC Images

This help page has been requested in the forums, and is now live. It gives some visual examples of common issues with MOC images and how to correct them. You may also have noticed some of these examples in the Submit a MOC form before you have uploaded any images. We hope this will reduce the number of MOCs (particularly from new users) that get rejected on image.

It also contains a guide about how to use image transparency, which is mostly useful for MOCs where you are designing a stand or base.

If you design car MOCs and would be happy for me to use one of your MOC images as a "good" example, please let me know in comments!

Auto Approve

Information on Auto-Approve has been consolidated onto this page and expanded slightly to address common questions on the subject.

RULEs page

Updates to the RULES page are tracked in the table at the bottom of the page. Thanks to feedback on the forums we added clarity about brick built content in the main image. There were some other minor edits including removing a duplicated rule, and moving the rule about English titles/descriptions.

Themes

Several new themes have been introduced since our last update.

Colors

In January, two new colors have been introduced: Warm Pink and Blue Violet.

 

Site Features/Enhancements

It's been nearly 6 months since the last update, so there have been hundreds of changes made to the site functionality in that time. You can see all of them in the commit log.

Here are some of the highlights.

  • Added the Models tab for Sets - allowing you to upload/download digital model files (eg BrickLink Studio) of the official Sets. We have about 250 added so far.
  • Added "Ignore Mold Variations" option to the Buy Parts tabs. This helps get a lot more 100% matches for external stores which often catalog parts differently resulting in no matches when in fact they are the same part. BrickOwl/ToyPro stores only as BrickLink do not provide the necessary data for this calculation.
  • For (some) MOCs where we can find an external store that has 100% of the parts (New/Ignore Molds) show a link to that store in the main section without having to go to the Buy Parts tab. This calculation is very expensive so only shows up on select MOCs. Again, it does not include BrickLink stores as they do not provide the required data.
  • Some Workbench tweaks to try and improve visibility, and some changes to the underlying stats collection to allow better analytics (not visible yet).
  • We migrated to a new external system for scheduling/posting our social media MOC promotions. After some initial hiccups it's been working well with far more reliable posts than the previous system. The layout of the posts has also changed a little to be more up to date with the latest social media styles which seems to have improved engagement slightly.
  • Lots of improvements to handling email issues and making it easier to re-enable notifications. These improve our email deliverability and give users better visibility into email errors.
  • Several changes to the MOC submission approvals process, most of which is not visible to users. But it includes some additional auto-validation checks that might show up when submitting. All in an effort to streamline our approvals process.
  • Automated and on-request payouts have been added for our RebrickMat Affiliates.
  • Sooo many tweaks to detecting and blocking bots and other automated scraping tools. The use of these is against our Terms and significantly increases the amount of hardware we need to keep the site running. Unfortunately, these efforts sometimes cause real users to get the annoying "are you human?" challenges and throttled responses.

In other news, we recently welcomed dmonti79 to the MOC Approvals team to help us with the growing number of MOC submissions.

That is all for this admin update, feel free to ask us questions in the comments!

 

 

 

RebrickMat - LEGO Building Mat
Gringotts Wizading Bank
DJDT

Time

Resource usage

Resource Value
User CPU time 285.403 msec
System CPU time 12.464 msec
Total CPU time 297.867 msec
Elapsed time 1304.431 msec
Context switches 206 voluntary, 3 involuntary

Browser timing

Timing attribute Timeline Milliseconds since navigation start (+length)

SQL queries from 1 connection

  • default 1001.52 ms (40 queries including 31 similar and 6 duplicates )
Query Timeline Time (ms) Action
SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 921)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 921) LIMIT 21
9 similar queries.
0.40

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(119)
  article = get_object_or_404(Article, id=article_id)

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector",
       (SIMILARITY("blog_article"."title", 'Admin update') + SIMILARITY("blog_article"."body", 'Rebrickable is under constant change. To keep you up to date it is time for another admin news article. The period between these can vary depending on the amount of news we have to bring. The blogs are all tagged so you can easily find others in the series. Rules Reminder - Scraping Scraping is where people use automated tools to harvest data from websites intended for human interactions. As per the Terms of Service, scraping of Rebrickable pages is not allowed. This is not a new rule, but Nathan has recently improved bot detection and enforcing this more than in the past. Why is this important? MOC designers trust us to protect their data. As the largest MOC marketplace we are often targeted by theives, or people wanting to train AI, or others with less than honourable intentions. This is why the majority of data relating the MOCs is not avaliable via the API or download files. This is also why you now need to be logged in when downloading free instructions. But I''m making an app that needs this data! Rebrickable does offer a large amount of the data on the website both via an API and via download files. Things like set info, part numbers and relationships, etc are free to use, even for commercial purposes. However we do recommend giving credit to where the data came from. If your project relies on data not avaliable via these methods, you can create a suggestion on the forums for this to be introduced, but be prepared that the answer may be privacy issues prevent us from sharing it. New Help Pages Rebrickable has some new help pages! Tips for Creating MOC Images This help page has been requested in the forums, and is now live. It gives some visual examples of common issues with MOC images and how to correct them. You may also have noticed some of these examples in the Submit a MOC form before you have uploaded any images. We hope this will reduce the number of MOCs (particularly from new users) that get rejected on image. It also contains a guide about how to use image transparency, which is mostly useful for MOCs where you are designing a stand or base. If you design car MOCs and would be happy for me to use one of your MOC images as a "good" example, please let me know in comments! Auto Approve Information on Auto-Approve has been consolidated onto this page and expanded slightly to address common questions on the subject. RULEs page Updates to the RULES page are tracked in the table at the bottom of the page. Thanks to feedback on the forums we added clarity about brick built content in the main image. There were some other minor edits including removing a duplicated rule, and moving the rule about English titles/descriptions. Themes Several new themes have been introduced since our last update. Collectible Minifigures has reached Series 28, and Series 29. Editions is an all-new theme. Its focus is not really clear: lego.com only mentions a partnership with FIFA, but also lists the non-FIFA 43019-1 Football, Formula 1 helmets and a Nike shoe. So it might be a sort of Icons-for-sports? Some...                 ...body once told me Shrek is coming in LEGO form. We’re going up, up, up with the new Kpop Demon Hunters! Duplo has gotten some sub-themes: Bluey Peppa Pig Seasonal City also received a new subtheme: Space Educational and Dacta has released a new sub-theme with sets available for the general public: Learning at Home Colors In January, two new colors have been introduced: Warm Pink and Blue Violet.   Site Features/Enhancements It''s been nearly 6 months since the last update, so there have been hundreds of changes made to the site functionality in that time. You can see all of them in the commit log. Here are some of the highlights. Added the Models tab for Sets - allowing you to upload/download digital model files (eg BrickLink Studio) of the official Sets. We have about 250 added so far. Added "Ignore Mold Variations" option to the Buy Parts tabs. This helps get a lot more 100% matches for external stores which often catalog parts differently resulting in no matches when in fact they are the same part. BrickOwl/ToyPro stores only as BrickLink do not provide the necessary data for this calculation. For (some) MOCs where we can find an external store that has 100% of the parts (New/Ignore Molds) show a link to that store in the main section without having to go to the Buy Parts tab. This calculation is very expensive so only shows up on select MOCs. Again, it does not include BrickLink stores as they do not provide the required data. Some Workbench tweaks to try and improve visibility, and some changes to the underlying stats collection to allow better analytics (not visible yet). We migrated to a new external system for scheduling/posting our social media MOC promotions. After some initial hiccups it''s been working well with far more reliable posts than the previous system. The layout of the posts has also changed a little to be more up to date with the latest social media styles which seems to have improved engagement slightly. Lots of improvements to handling email issues and making it easier to re-enable notifications. These improve our email deliverability and give users better visibility into email errors. Several changes to the MOC submission approvals process, most of which is not visible to users. But it includes some additional auto-validation checks that might show up when submitting. All in an effort to streamline our approvals process. Automated and on-request payouts have been added for our RebrickMat Affiliates. Sooo many tweaks to detecting and blocking bots and other automated scraping tools. The use of these is against our Terms and significantly increases the amount of hardware we need to keep the site running. Unfortunately, these efforts sometimes cause real users to get the annoying "are you human?" challenges and throttled responses. In other news, we recently welcomed dmonti79 to the MOC Approvals team to help us with the growing number of MOC submissions. That is all for this admin update, feel free to ask us questions in the comments!      ')) AS "similarity",
       "auth_user"."id",
       "auth_user"."password",
       "auth_user"."last_login",
       "auth_user"."is_superuser",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."date_joined"
  FROM
"blog_article"
  LEFT OUTER JOIN
"auth_user"
    ON
("blog_article"."author_id" = "auth_user"."id")
 WHERE
("blog_article"."is_active" AND "blog_article"."published_date" > '2023-11-16T23:57:37.720306+00:00'::timestamptz AND NOT ("blog_article"."id" = 921))
 ORDER BY
19 DESC, "blog_article"."published_date" DESC
 LIMIT
15
SELECT "blog_article"."id", "blog_article"."title", "blog_article"."author_id", "blog_article"."published_date", "blog_article"."is_active", "blog_article"."body", "blog_article"."meta_description", "blog_article"."meta_img", "blog_article"."slug", "blog_article"."category_id", "blog_article"."ads", "blog_article"."show_ads_for_set_num", "blog_article"."review_for_set_num", "blog_article"."status", "blog_article"."scheduled_net", "blog_article"."ready_for_review_date", "blog_article"."is_sensitive", "blog_article"."search_vector", (SIMILARITY("blog_article"."title", 'Admin update') + SIMILARITY("blog_article"."body", 'Rebrickable is under constant change. To keep you up to date it is time for another admin news article. The period between these can vary depending on the amount of news we have to bring. The blogs are all tagged so you can easily find others in the series. Rules Reminder - Scraping Scraping is where people use automated tools to harvest data from websites intended for human interactions. As per the Terms of Service, scraping of Rebrickable pages is not allowed. This is not a new rule, but Nathan has recently improved bot detection and enforcing this more than in the past. Why is this important? MOC designers trust us to protect their data. As the largest MOC marketplace we are often targeted by theives, or people wanting to train AI, or others with less than honourable intentions. This is why the majority of data relating the MOCs is not avaliable via the API or download files. This is also why you now need to be logged in when downloading free instructions. But I''m making an app that needs this data! Rebrickable does offer a large amount of the data on the website both via an API and via download files. Things like set info, part numbers and relationships, etc are free to use, even for commercial purposes. However we do recommend giving credit to where the data came from. If your project relies on data not avaliable via these methods, you can create a suggestion on the forums for this to be introduced, but be prepared that the answer may be privacy issues prevent us from sharing it. New Help Pages Rebrickable has some new help pages! Tips for Creating MOC Images This help page has been requested in the forums, and is now live. It gives some visual examples of common issues with MOC images and how to correct them. You may also have noticed some of these examples in the Submit a MOC form before you have uploaded any images. We hope this will reduce the number of MOCs (particularly from new users) that get rejected on image. It also contains a guide about how to use image transparency, which is mostly useful for MOCs where you are designing a stand or base. If you design car MOCs and would be happy for me to use one of your MOC images as a "good" example, please let me know in comments! Auto Approve Information on Auto-Approve has been consolidated onto this page and expanded slightly to address common questions on the subject. RULEs page Updates to the RULES page are tracked in the table at the bottom of the page. Thanks to feedback on the forums we added clarity about brick built content in the main image. There were some other minor edits including removing a duplicated rule, and moving the rule about English titles/descriptions. Themes Several new themes have been introduced since our last update. Collectible Minifigures has reached Series 28, and Series 29. Editions is an all-new theme. Its focus is not really clear: lego.com only mentions a partnership with FIFA, but also lists the non-FIFA 43019-1 Football, Formula 1 helmets and a Nike shoe. So it might be a sort of Icons-for-sports? Some...                 ...body once told me Shrek is coming in LEGO form. We’re going up, up, up with the new Kpop Demon Hunters! Duplo has gotten some sub-themes: Bluey Peppa Pig Seasonal City also received a new subtheme: Space Educational and Dacta has released a new sub-theme with sets available for the general public: Learning at Home Colors In January, two new colors have been introduced: Warm Pink and Blue Violet.   Site Features/Enhancements It''s been nearly 6 months since the last update, so there have been hundreds of changes made to the site functionality in that time. You can see all of them in the commit log. Here are some of the highlights. Added the Models tab for Sets - allowing you to upload/download digital model files (eg BrickLink Studio) of the official Sets. We have about 250 added so far. Added "Ignore Mold Variations" option to the Buy Parts tabs. This helps get a lot more 100% matches for external stores which often catalog parts differently resulting in no matches when in fact they are the same part. BrickOwl/ToyPro stores only as BrickLink do not provide the necessary data for this calculation. For (some) MOCs where we can find an external store that has 100% of the parts (New/Ignore Molds) show a link to that store in the main section without having to go to the Buy Parts tab. This calculation is very expensive so only shows up on select MOCs. Again, it does not include BrickLink stores as they do not provide the required data. Some Workbench tweaks to try and improve visibility, and some changes to the underlying stats collection to allow better analytics (not visible yet). We migrated to a new external system for scheduling/posting our social media MOC promotions. After some initial hiccups it''s been working well with far more reliable posts than the previous system. The layout of the posts has also changed a little to be more up to date with the latest social media styles which seems to have improved engagement slightly. Lots of improvements to handling email issues and making it easier to re-enable notifications. These improve our email deliverability and give users better visibility into email errors. Several changes to the MOC submission approvals process, most of which is not visible to users. But it includes some additional auto-validation checks that might show up when submitting. All in an effort to streamline our approvals process. Automated and on-request payouts have been added for our RebrickMat Affiliates. Sooo many tweaks to detecting and blocking bots and other automated scraping tools. The use of these is against our Terms and significantly increases the amount of hardware we need to keep the site running. Unfortunately, these efforts sometimes cause real users to get the annoying "are you human?" challenges and throttled responses. In other news, we recently welcomed dmonti79 to the MOC Approvals team to help us with the growing number of MOC submissions. That is all for this admin update, feel free to ask us questions in the comments!      ')) AS "similarity", "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "blog_article" LEFT OUTER JOIN "auth_user" ON ("blog_article"."author_id" = "auth_user"."id") WHERE ("blog_article"."is_active" AND "blog_article"."published_date" > '2023-11-16T23:57:37.720306+00:00'::timestamptz AND NOT ("blog_article"."id" = 921)) ORDER BY 19 DESC, "blog_article"."published_date" DESC LIMIT 15
950.44

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(148)
  related_articles = article.get_related_articles(num_sidebar_posts)

/home/nathan/rb/site/./cache/utils.py in cache_wrapper(98)
  result = method(instance, *args, **kwargs)

/home/nathan/rb/site/./blog/models.py in get_related_articles(289)
  return list(Article.objects.select_related('author').filter(published_date__gt=timezone.now()-timedelta(days=365*3)).annotate(similarity=TrigramSimilarity('title', self.title)+TrigramSimilarity('body', body)).exclude(id=self.id).order_by('-similarity', '-published_date')[:num])

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector",
       "auth_user"."id",
       "auth_user"."password",
       "auth_user"."last_login",
       "auth_user"."is_superuser",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."date_joined"
  FROM
"blog_article"
  LEFT OUTER JOIN
"auth_user"
    ON
("blog_article"."author_id" = "auth_user"."id")
  LEFT OUTER JOIN
"blog_articlestats"
    ON
("blog_article"."id" = "blog_articlestats"."article_id")
 WHERE
("blog_article"."is_active" AND "blog_article"."published_date" > '2025-11-15T23:57:38.685617+00:00'::timestamptz)
 ORDER BY
"blog_articlestats"."hits" DESC
 LIMIT
15
SELECT ••• FROM "blog_article" LEFT OUTER JOIN "auth_user" ON ("blog_article"."author_id" = "auth_user"."id") LEFT OUTER JOIN "blog_articlestats" ON ("blog_article"."id" = "blog_articlestats"."article_id") WHERE ("blog_article"."is_active" AND "blog_article"."published_date" > '2025-11-15T23:57:38.685617+00:00'::timestamptz) ORDER BY "blog_articlestats"."hits" DESC LIMIT 15
2.59

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(149)
  popular_articles = Article.get_popular_articles(num_sidebar_posts)

/home/nathan/rb/site/./cache/utils.py in cache_wrapper(101)
  caches[cache_key].set(method_key, result, seconds)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/client/hash.py in set(344)
  return self._run_cmd("set", key, False, *args, **kwargs)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/client/hash.py in _run_cmd(322)
  return self._safely_run_func(client, func, default_val, *args, **kwargs)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/client/hash.py in _safely_run_func(211)
  result = func(*args, **kwargs)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/client/base.py in set(1424)
  return client.set(key, value, expire=expire, noreply=noreply, flags=flags)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/client/base.py in set(475)
  return self._store_cmd(b"set", {key: value}, expire, noreply, flags=flags)[key]

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/client/base.py in _store_cmd(1196)
  data, data_flags = self.serde.serialize(key, data)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/serde.py in serialize(119)
  return self._serialize_func(key, value)

/home/nathan/venv_rb310/lib/python3.10/site-packages/pymemcache/serde.py in _python_memcache_serializer(58)
  pickler.dump(value)

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 646)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 646) LIMIT 21
9 similar queries.
0.27

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(50)
  {'name': 'Designer Spotlights', 'tag': 'designer-spotlight', 'article': Article.objects.get(id=646)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 720)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 720) LIMIT 21
9 similar queries.
0.31

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(51)
  {'name': 'New Set Releases', 'tag': 'sets', 'article': Article.objects.get(id=720)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 605)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 605) LIMIT 21
9 similar queries.
0.21

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(52)
  {'name': 'Into the Archives', 'tag': 'into-the-archives', 'article': Article.objects.get(id=605)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 705)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 705) LIMIT 21
9 similar queries.
0.26

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(53)
  {'name': 'Mini MOC Madness', 'tag': 'mini-moc-madness', 'article': Article.objects.get(id=705)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 616)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 616) LIMIT 21
9 similar queries.
0.21

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(54)
  {'name': 'Is This LEGO?', 'tag': 'is-this-lego', 'article': Article.objects.get(id=616)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 462)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 462) LIMIT 21
9 similar queries.
0.21

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(55)
  {'name': 'Tips & Useful Info', 'tag': 'tips', 'article': Article.objects.get(id=462)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 279)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 279) LIMIT 21
9 similar queries.
0.18

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(56)
  {'name': 'Rebricksberg', 'tag': 'rebricksberg', 'article': Article.objects.get(id=279)},

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND "blog_article"."id" = 249)
 LIMIT
21
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND "blog_article"."id" = 249) LIMIT 21
9 similar queries.
0.13

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(57)
  {'name': 'The Good, The Bad, & The Ugly', 'tag': 'good-bad-ugly', 'article': Article.objects.get(id=249)},

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('designer-spotlight'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('designer-spotlight'))
8 similar queries.
2.51

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('sets'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('sets'))
8 similar queries.
2.14

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('into-the-archives'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('into-the-archives'))
8 similar queries.
2.14

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('mini-moc-madness'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('mini-moc-madness'))
8 similar queries.
2.13

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('is-this-lego'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('is-this-lego'))
8 similar queries.
2.13

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('tips'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('tips'))
8 similar queries.
2.12

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('rebricksberg'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('rebricksberg'))
8 similar queries.
2.14

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT COUNT(*) AS "__count"
  FROM
"blog_article"
 INNER JOIN
"taggit_taggeditem"
    ON
("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_tag"
    ON
("taggit_taggeditem"."tag_id" = "taggit_tag"."id")
 WHERE
("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('good-bad-ugly'))
SELECT ••• FROM "blog_article" INNER JOIN "taggit_taggeditem" ON ("blog_article"."id" = "taggit_taggeditem"."object_id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_tag" ON ("taggit_taggeditem"."tag_id" = "taggit_tag"."id") WHERE ("blog_article"."is_active" AND UPPER("taggit_tag"."slug"::text) = UPPER('good-bad-ugly'))
8 similar queries.
2.09

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(150)
  article_series_images = get_series()

/home/nathan/rb/site/./blog/views.py in get_series(60)
  s['num_posts'] = Article.objects.filter(tags__slug__iexact=s['tag']).count()

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND (("blog_article"."published_date" = '2026-04-30T00:00:00.079077+00:00'::timestamptz AND "blog_article"."id" > 921) OR "blog_article"."published_date" > '2026-04-30T00:00:00.079077+00:00'::timestamptz))
 ORDER BY
"blog_article"."published_date" ASC, "blog_article"."id" ASC
 LIMIT
1
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND (("blog_article"."published_date" = '2026-04-30T00:00:00.079077+00:00'::timestamptz AND "blog_article"."id" > 921) OR "blog_article"."published_date" > '2026-04-30T00:00:00.079077+00:00'::timestamptz)) ORDER BY "blog_article"."published_date" ASC, "blog_article"."id" ASC LIMIT 1
0.58

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(155)
  article.next = Article.get_next_by_published_date(article)

/usr/lib/python3.10/functools.py in _method(388)
  return self.func(cls_or_self, *self.args, *args, **keywords)

SELECT "blog_article"."id",
       "blog_article"."title",
       "blog_article"."author_id",
       "blog_article"."published_date",
       "blog_article"."is_active",
       "blog_article"."body",
       "blog_article"."meta_description",
       "blog_article"."meta_img",
       "blog_article"."slug",
       "blog_article"."category_id",
       "blog_article"."ads",
       "blog_article"."show_ads_for_set_num",
       "blog_article"."review_for_set_num",
       "blog_article"."status",
       "blog_article"."scheduled_net",
       "blog_article"."ready_for_review_date",
       "blog_article"."is_sensitive",
       "blog_article"."search_vector"
  FROM
"blog_article"
 WHERE
("blog_article"."is_active" AND (("blog_article"."published_date" = '2026-04-30T00:00:00.079077+00:00'::timestamptz AND "blog_article"."id" < 921) OR "blog_article"."published_date" < '2026-04-30T00:00:00.079077+00:00'::timestamptz))
 ORDER BY
"blog_article"."published_date" DESC, "blog_article"."id" DESC
 LIMIT
1
SELECT ••• FROM "blog_article" WHERE ("blog_article"."is_active" AND (("blog_article"."published_date" = '2026-04-30T00:00:00.079077+00:00'::timestamptz AND "blog_article"."id" < 921) OR "blog_article"."published_date" < '2026-04-30T00:00:00.079077+00:00'::timestamptz)) ORDER BY "blog_article"."published_date" DESC, "blog_article"."id" DESC LIMIT 1
0.44

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(159)
  article.prev = Article.get_previous_by_published_date(article)

/usr/lib/python3.10/functools.py in _method(388)
  return self.func(cls_or_self, *self.args, *args, **keywords)

SELECT "auth_user"."id",
       "auth_user"."password",
       "auth_user"."last_login",
       "auth_user"."is_superuser",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."date_joined"
  FROM
"auth_user"
 WHERE
"auth_user"."id" = 159879
 LIMIT
21
SELECT ••• FROM "auth_user" WHERE "auth_user"."id" = 159879 LIMIT 21
0.15

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

54 "dateModified": "{{ article.published_date|date:'c' }}",
55 "author": {
56 "@type": "Person",
57 "name": "{{ article.author.username }}"
58 },
59 "publisher": {
60 "@type": "Organization",
61 "name": "Rebrickable",

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT "countries_plus_country"."iso",
       "countries_plus_country"."iso3",
       "countries_plus_country"."iso_numeric",
       "countries_plus_country"."fips",
       "countries_plus_country"."name",
       "countries_plus_country"."capital",
       "countries_plus_country"."area",
       "countries_plus_country"."population",
       "countries_plus_country"."continent",
       "countries_plus_country"."tld",
       "countries_plus_country"."currency_code",
       "countries_plus_country"."currency_symbol",
       "countries_plus_country"."currency_name",
       "countries_plus_country"."phone",
       "countries_plus_country"."postal_code_format",
       "countries_plus_country"."postal_code_regex",
       "countries_plus_country"."languages",
       "countries_plus_country"."geonameid",
       "countries_plus_country"."neighbours",
       "countries_plus_country"."equivalent_fips_code"
  FROM
"countries_plus_country"
 WHERE
"countries_plus_country"."iso" = 'US'
 LIMIT
21
SELECT ••• FROM "countries_plus_country" WHERE "countries_plus_country"."iso" = 'US' LIMIT 21
0.10

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./rb/templatetags/rb_geo.py in geo_currency(20)
  geo_data = user.geo.get_user_currency()

/home/nathan/rb/site/./geo/geo.py in get_user_currency(253)
  country = Country.objects.get(iso=country_code)

74 </a>
75 </li>
76 <li>
77 {% geo_currency request.user %}
78 </li>
79 {% comment %}
80 <li class="hidden-xs hidden-sm">
81 <a href={% if request.user.is_authenticated %}"{% url 'user_profile_settings' request.user.get_username %}#personalisation"{% else %}"#" onclick="return false;"{% endif %} title="All date/times are being converted to this timezone">{% get_user_timezone request.user %}</a>

/home/nathan/rb/site/rb/templates/rb/includes/topbar.html

SELECT "blog_articlecategory"."id",
       "blog_articlecategory"."name"
  FROM
"blog_articlecategory"
 WHERE
"blog_articlecategory"."id" = 3
 LIMIT
21
SELECT ••• FROM "blog_articlecategory" WHERE "blog_articlecategory"."id" = 3 LIMIT 21
0.11

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

18
19 {% block breadcrumbs %}
20 {% breadcrumb "Blog Posts" "blog_index" %}
21 {% breadcrumb article.category "blog_by_category" article.category %}
22 {% breadcrumb article.title "blog_article" article.id %}
23 {% endblock %}
24
25 {% block meta_description %}{{ article.meta_description }}{% endblock meta_description %}

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT "auth_user"."id",
       "auth_user"."password",
       "auth_user"."last_login",
       "auth_user"."is_superuser",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."date_joined"
  FROM
"auth_user"
 WHERE
"auth_user"."username" = 'icedragonj'
 LIMIT
21
SELECT ••• FROM "auth_user" WHERE "auth_user"."username" = 'icedragonj' LIMIT 21
2 similar queries. Duplicated 2 times.
0.10

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./avatar/templatetags/avatar_tags.py in avatar_url(33)
  avatar_url = provider.get_avatar_url(user, size)

/home/nathan/rb/site/./avatar/providers.py in get_avatar_url(48)
  avatar = get_primary_avatar(user, size)

/home/nathan/rb/site/./avatar/utils.py in get_primary_avatar(112)
  user = get_user(user)

/home/nathan/rb/site/./avatar/utils.py in get_user(33)
  return get_user_model().objects.get_by_natural_key(username)

92 <!--<div class="flex-row">
93 <div class="mr-10 hidden-xs" style="width: 50px">
94 <a href="{% url 'blog_by_author' article.author.username %}">
95 <img data-src="{% avatar_url article.author.username 75 %}" width="50px" height="50px">
96 </a>
97 </div>
98 <div class="flex-expand">
99 <div class="heading-title heading-border-bottom heading-color mb-10">

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT "avatar_avatar"."id",
       "avatar_avatar"."user_id",
       "avatar_avatar"."primary",
       "avatar_avatar"."avatar",
       "avatar_avatar"."date_uploaded"
  FROM
"avatar_avatar"
 WHERE
"avatar_avatar"."user_id" = 159879
 ORDER BY
"avatar_avatar"."primary" DESC, "avatar_avatar"."date_uploaded" DESC
 LIMIT
1
SELECT ••• FROM "avatar_avatar" WHERE "avatar_avatar"."user_id" = 159879 ORDER BY "avatar_avatar"."primary" DESC, "avatar_avatar"."date_uploaded" DESC LIMIT 1
2 similar queries. Duplicated 2 times.
0.11

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./avatar/templatetags/avatar_tags.py in avatar_url(33)
  avatar_url = provider.get_avatar_url(user, size)

/home/nathan/rb/site/./avatar/providers.py in get_avatar_url(48)
  avatar = get_primary_avatar(user, size)

/home/nathan/rb/site/./avatar/utils.py in get_primary_avatar(120)
  avatar = user.avatar_set.order_by("-primary", "-date_uploaded")[0]

92 <!--<div class="flex-row">
93 <div class="mr-10 hidden-xs" style="width: 50px">
94 <a href="{% url 'blog_by_author' article.author.username %}">
95 <img data-src="{% avatar_url article.author.username 75 %}" width="50px" height="50px">
96 </a>
97 </div>
98 <div class="flex-expand">
99 <div class="heading-title heading-border-bottom heading-color mb-10">

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT COUNT(*) AS "__count"
  FROM
"threadedcomments_comment"
 INNER JOIN
"django_comments"
    ON
("threadedcomments_comment"."comment_ptr_id" = "django_comments"."id")
 WHERE
("django_comments"."content_type_id" = 12 AND "django_comments"."object_pk" = '921' AND "django_comments"."site_id" = 1 AND "django_comments"."is_public" AND NOT "django_comments"."is_removed")
SELECT ••• FROM "threadedcomments_comment" INNER JOIN "django_comments" ON ("threadedcomments_comment"."comment_ptr_id" = "django_comments"."id") WHERE ("django_comments"."content_type_id" = 12 AND "django_comments"."object_pk" = '921' AND "django_comments"."site_id" = 1 AND "django_comments"."is_public" AND NOT "django_comments"."is_removed")
2 similar queries. Duplicated 2 times.
14.11

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/venv_rb310/lib/python3.10/site-packages/django_comments/templatetags/comments.py in render(72)
  context[self.as_varname] = self.get_context_value_from_queryset(context, qs)

/home/nathan/venv_rb310/lib/python3.10/site-packages/threadedcomments/templatetags/threadedcomments_tags.py in get_context_value_from_queryset(116)
  return qs.count()

24
25 <div class="rb-article-card__meta flex-right hidden-xs hidden-sm">
26 {% if full_layout %}
27 {% get_comment_count for article as num_comments %}
28 <div>
29 <a href="{% url 'blog_article_w_slug' article.id article.slug %}#comments">
30 <i class="fa fa-comment-o"></i>
31 {{ num_comments }}<span> Comment{{ num_comments|pluralize }}</span>

/home/nathan/rb/site/blog/templates/blog/includes/render_article_byline.html

SELECT "blog_articlestats"."article_id",
       "blog_articlestats"."hits"
  FROM
"blog_articlestats"
 WHERE
"blog_articlestats"."article_id" = 921
 LIMIT
21
SELECT ••• FROM "blog_articlestats" WHERE "blog_articlestats"."article_id" = 921 LIMIT 21
0.10

Connection: default

Transaction status: In transaction

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/usr/lib/python3.10/contextlib.py in inner(79)
  return func(*args, **kwds)

/home/nathan/venv_rb310/lib/python3.10/site-packages/annoying/fields.py in __get__(36)
  .__get__(instance, instance_type)

33 </div>
34 {% endif %}
35
36 {% if article.stats.hits > 100 %}
37 <div>
38 <i class="fa fa-line-chart"></i>
39 <span>{{ article.stats.hits|floor_100 }} views</span>
40 </div>

/home/nathan/rb/site/blog/templates/blog/includes/render_article_byline.html

SELECT "auth_user"."id",
       "auth_user"."password",
       "auth_user"."last_login",
       "auth_user"."is_superuser",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."date_joined"
  FROM
"auth_user"
 WHERE
"auth_user"."username" = 'icedragonj'
 LIMIT
21
SELECT ••• FROM "auth_user" WHERE "auth_user"."username" = 'icedragonj' LIMIT 21
2 similar queries. Duplicated 2 times.
0.08

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./avatar/templatetags/avatar_tags.py in avatar_url(33)
  avatar_url = provider.get_avatar_url(user, size)

/home/nathan/rb/site/./avatar/providers.py in get_avatar_url(48)
  avatar = get_primary_avatar(user, size)

/home/nathan/rb/site/./avatar/utils.py in get_primary_avatar(112)
  user = get_user(user)

/home/nathan/rb/site/./avatar/utils.py in get_user(33)
  return get_user_model().objects.get_by_natural_key(username)

107 <div class="rb-article-card__top">
108 <span class="rb-article-card__avatar hidden-xs">
109 <a href="{% url 'blog_by_author' article.author.username %}">
110 <img data-src="{% avatar_url article.author.username 75 %}" width="50" height="50" alt="{{ article.author.username }}">
111 </a>
112 </span>
113
114 <h1 id="blog_title" class="rb-article-card__title rb-article-card__title--lg">

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT "avatar_avatar"."id",
       "avatar_avatar"."user_id",
       "avatar_avatar"."primary",
       "avatar_avatar"."avatar",
       "avatar_avatar"."date_uploaded"
  FROM
"avatar_avatar"
 WHERE
"avatar_avatar"."user_id" = 159879
 ORDER BY
"avatar_avatar"."primary" DESC, "avatar_avatar"."date_uploaded" DESC
 LIMIT
1
SELECT ••• FROM "avatar_avatar" WHERE "avatar_avatar"."user_id" = 159879 ORDER BY "avatar_avatar"."primary" DESC, "avatar_avatar"."date_uploaded" DESC LIMIT 1
2 similar queries. Duplicated 2 times.
0.08

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./avatar/templatetags/avatar_tags.py in avatar_url(33)
  avatar_url = provider.get_avatar_url(user, size)

/home/nathan/rb/site/./avatar/providers.py in get_avatar_url(48)
  avatar = get_primary_avatar(user, size)

/home/nathan/rb/site/./avatar/utils.py in get_primary_avatar(120)
  avatar = user.avatar_set.order_by("-primary", "-date_uploaded")[0]

107 <div class="rb-article-card__top">
108 <span class="rb-article-card__avatar hidden-xs">
109 <a href="{% url 'blog_by_author' article.author.username %}">
110 <img data-src="{% avatar_url article.author.username 75 %}" width="50" height="50" alt="{{ article.author.username }}">
111 </a>
112 </span>
113
114 <h1 id="blog_title" class="rb-article-card__title rb-article-card__title--lg">

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT COUNT(*) AS "__count"
  FROM
"threadedcomments_comment"
 INNER JOIN
"django_comments"
    ON
("threadedcomments_comment"."comment_ptr_id" = "django_comments"."id")
 WHERE
("django_comments"."content_type_id" = 12 AND "django_comments"."object_pk" = '921' AND "django_comments"."site_id" = 1 AND "django_comments"."is_public" AND NOT "django_comments"."is_removed")
SELECT ••• FROM "threadedcomments_comment" INNER JOIN "django_comments" ON ("threadedcomments_comment"."comment_ptr_id" = "django_comments"."id") WHERE ("django_comments"."content_type_id" = 12 AND "django_comments"."object_pk" = '921' AND "django_comments"."site_id" = 1 AND "django_comments"."is_public" AND NOT "django_comments"."is_removed")
2 similar queries. Duplicated 2 times.
0.31

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/venv_rb310/lib/python3.10/site-packages/django_comments/templatetags/comments.py in render(72)
  context[self.as_varname] = self.get_context_value_from_queryset(context, qs)

/home/nathan/venv_rb310/lib/python3.10/site-packages/threadedcomments/templatetags/threadedcomments_tags.py in get_context_value_from_queryset(116)
  return qs.count()

24
25 <div class="rb-article-card__meta flex-right hidden-xs hidden-sm">
26 {% if full_layout %}
27 {% get_comment_count for article as num_comments %}
28 <div>
29 <a href="{% url 'blog_article_w_slug' article.id article.slug %}#comments">
30 <i class="fa fa-comment-o"></i>
31 {{ num_comments }}<span> Comment{{ num_comments|pluralize }}</span>

/home/nathan/rb/site/blog/templates/blog/includes/render_article_byline.html

SELECT DISTINCT "taggit_tag"."id",
       "taggit_tag"."name",
       "taggit_tag"."slug",
       COUNT("blog_article"."id") AS "count"
  FROM
"taggit_tag"
 INNER JOIN
"taggit_taggeditem"
    ON
("taggit_tag"."id" = "taggit_taggeditem"."tag_id")
 INNER JOIN
"django_content_type"
    ON
("taggit_taggeditem"."content_type_id" = "django_content_type"."id")
  LEFT OUTER JOIN
"blog_article"
    ON
("taggit_taggeditem"."object_id" = "blog_article"."id" AND ("taggit_taggeditem"."content_type_id" = 12))
 INNER JOIN
"taggit_taggeditem" T5
    ON
("taggit_tag"."id" = T5."tag_id")
 INNER JOIN
"blog_article" T6
    ON
(T5."object_id" = T6."id" AND (T5."content_type_id" = 12))
 WHERE
("django_content_type"."app_label" = 'blog' AND "django_content_type"."model" = 'article' AND T6."id" = 921)
 GROUP BY
"taggit_tag"."id"
SELECT ••• FROM "taggit_tag" INNER JOIN "taggit_taggeditem" ON ("taggit_tag"."id" = "taggit_taggeditem"."tag_id") INNER JOIN "django_content_type" ON ("taggit_taggeditem"."content_type_id" = "django_content_type"."id") LEFT OUTER JOIN "blog_article" ON ("taggit_taggeditem"."object_id" = "blog_article"."id" AND ("taggit_taggeditem"."content_type_id" = 12)) INNER JOIN "taggit_taggeditem" T5 ON ("taggit_tag"."id" = T5."tag_id") INNER JOIN "blog_article" T6 ON (T5."object_id" = T6."id" AND (T5."content_type_id" = 12)) WHERE ("django_content_type"."app_label" = 'blog' AND "django_content_type"."model" = 'article' AND T6."id" = 921) GROUP BY "taggit_tag"."id"
1.15

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

1 <div id="blog_tags" class="clearfix tags_list mb-30">
2 {% for tag in article.tags_w_count %}
3 <a href="{% url 'blog_by_tag' tag.slug %}" class="tag {% if request.user.is_blogger %}deltag{% endif %}">
4 <span class="txt">{{ tag.name }}</span>
5 <span class="num">
6 <span class="relative">

/home/nathan/rb/site/blog/templates/blog/includes/render_tags.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.758035+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.758103+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 350 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.758021+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.758226+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.758035+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.758103+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 350 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.758021+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.758226+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
4 similar queries.
2.75

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(291)
  if not banners:

265 <h4 class="hidden-xs">TAGS</h4>
266 {% include 'blog/includes/render_tags.html' %}
267
268 {% render_banner 262 350 2 %}
269
270 {% include 'blog/includes/render_posts_preview_tabs.html' %}
271
272 <div class="mt-30">

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.758035+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.758103+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 350 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.758021+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.758226+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
 ORDER BY
1 DESC, RANDOM() ASC
 LIMIT
1
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.758035+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.758103+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 350 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.758021+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.758226+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US') ORDER BY 1 DESC, RANDOM() ASC LIMIT 1
4 similar queries.
1.32

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(298)
  banner = banners.order_by('-area', '?')[0]

265 <h4 class="hidden-xs">TAGS</h4>
266 {% include 'blog/includes/render_tags.html' %}
267
268 {% render_banner 262 350 2 %}
269
270 {% include 'blog/includes/render_posts_preview_tabs.html' %}
271
272 <div class="mt-30">

/home/nathan/rb/site/blog/templates/blog/blog_article.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.767591+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.767652+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.767580+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.767765+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.767591+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.767652+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.767580+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.767765+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
4 similar queries.
1.57

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(291)
  if not banners:

37 {% include 'blog/includes/render_posts_preview.html' with article=related_article %}
38 </div>
39 {% endfor %}
40 {% render_banner 262 600 5 %}
41 </div>
42 {% endif %}
43 <div id="tab_series" class="tab-pane {% if not related_articles %}active{% endif %}" role="tabpanel">
44 {% for series in article_series_images %}

/home/nathan/rb/site/blog/templates/blog/includes/render_posts_preview_tabs.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.767591+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.767652+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.767580+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.767765+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
 ORDER BY
1 DESC, RANDOM() ASC
 LIMIT
1
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.767591+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.767652+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.767580+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.767765+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US') ORDER BY 1 DESC, RANDOM() ASC LIMIT 1
4 similar queries.
1.10

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(298)
  banner = banners.order_by('-area', '?')[0]

37 {% include 'blog/includes/render_posts_preview.html' with article=related_article %}
38 </div>
39 {% endfor %}
40 {% render_banner 262 600 5 %}
41 </div>
42 {% endif %}
43 <div id="tab_series" class="tab-pane {% if not related_articles %}active{% endif %}" role="tabpanel">
44 {% for series in article_series_images %}

/home/nathan/rb/site/blog/templates/blog/includes/render_posts_preview_tabs.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.772357+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.772415+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.772349+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.772528+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.772357+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.772415+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.772349+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.772528+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
4 similar queries.
1.47

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(291)
  if not banners:

66 </div>
67 {% endfor %}
68
69 {% render_banner 262 600 5 %}
70 </div>
71 <div id="tab_popular" class="tab-pane" role="tabpanel">
72 {% for popular_article in popular_articles %}
73 <div class="mb-30">

/home/nathan/rb/site/blog/templates/blog/includes/render_posts_preview_tabs.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.772357+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.772415+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.772349+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.772528+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
 ORDER BY
1 DESC, RANDOM() ASC
 LIMIT
1
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.772357+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.772415+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.772349+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.772528+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US') ORDER BY 1 DESC, RANDOM() ASC LIMIT 1
4 similar queries.
1.10

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(298)
  banner = banners.order_by('-area', '?')[0]

66 </div>
67 {% endfor %}
68
69 {% render_banner 262 600 5 %}
70 </div>
71 <div id="tab_popular" class="tab-pane" role="tabpanel">
72 {% for popular_article in popular_articles %}
73 <div class="mb-30">

/home/nathan/rb/site/blog/templates/blog/includes/render_posts_preview_tabs.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.779033+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.779092+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.779023+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.779209+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.779033+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.779092+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.779023+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.779209+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
4 similar queries.
1.09

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(291)
  if not banners:

74 {% include 'blog/includes/render_posts_preview.html' with article=popular_article %}
75 </div>
76 {% endfor %}
77 {% render_banner 262 600 5 %}
78 </div>
79 </div>
80 </div>
81

/home/nathan/rb/site/blog/templates/blog/includes/render_posts_preview_tabs.html

SELECT (width*height) AS "area",
       "ads_banner"."id",
       "ads_banner"."width",
       "ads_banner"."height",
       "ads_banner"."start_date",
       "ads_banner"."end_date",
       "ads_banner"."country_code",
       "ads_banner"."html"
  FROM
"ads_banner"
 WHERE
("ads_banner"."start_date" < '2026-11-15T23:57:38.779033+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.779092+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.779023+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.779209+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US')
 ORDER BY
1 DESC, RANDOM() ASC
 LIMIT
1
SELECT ••• FROM "ads_banner" WHERE ("ads_banner"."start_date" < '2026-11-15T23:57:38.779033+00:00'::timestamptz AND ("ads_banner"."end_date" > '2026-11-15T23:57:38.779092+00:00'::timestamptz OR "ads_banner"."end_date" IS NULL) AND "ads_banner"."height" <= 600 AND "ads_banner"."start_date" < '2026-11-15T23:57:38.779023+00:00'::timestamptz AND "ads_banner"."width" <= 262 AND ("ads_banner"."end_date" IS NULL OR "ads_banner"."end_date" > '2026-11-15T23:57:38.779209+00:00'::timestamptz) AND "ads_banner"."country_code" = 'US') ORDER BY 1 DESC, RANDOM() ASC LIMIT 1
4 similar queries.
1.08

Connection: default

Transaction status: Idle

/home/nathan/rb/site/./blog/views.py in blog_article_w_slug(236)
  return blog_article(request, article_id)

/home/nathan/rb/site/./blog/views.py in blog_article(213)
  return cached_blog_article(request, article.id)

/home/nathan/rb/site/./rb/views/decorators/auth.py in wrapper(169)
  result = view_func(request, *args, **kwargs)

/home/nathan/rb/site/./blog/views.py in cached_blog_article(209)
  return render(request, 'blog/blog_article.html', context)

/home/nathan/rb/site/./ads/templatetags/ads/drawing.py in render_banner(298)
  banner = banners.order_by('-area', '?')[0]

74 {% include 'blog/includes/render_posts_preview.html' with article=popular_article %}
75 </div>
76 {% endfor %}
77 {% render_banner 262 600 5 %}
78 </div>
79 </div>
80 </div>
81

/home/nathan/rb/site/blog/templates/blog/includes/render_posts_preview_tabs.html

Log messages

No messages logged.