accurate page view count in Django - django

What is a good approach to keeping accurate counts of how many times a page has been viewed?
I'm using Django. Specifically, I don't want refreshing the page to up the count.

As far as I'm aware, no browsers out there at the moment send any kind of message/header to the server saying whether the request was from a refresh or not.
The only way I can see to not count a user refreshing the page is to track the IPs and times that a user views a page, and then if the user last viewed the page less than 30 minutes ago, say, you would dismiss it as a refresh and not increment the page view count.
IMO most page refreshes should be counted as a page view anyway, as the only reason I have for refreshing is to see new data that might have been added, or the occasional accidental refresh/reloading after a browser crash (which the above method would dismiss).

You could give each user cookie, that expires at the end of the day, containing a unique number. If he reloads a page you can check wether she has been counted already that day.

You could create a table with unique visitors of the pages, e.g. VisitorIP + X-Forwarded-For content, User-Agent string along with a PageID of some sorts. If the data itself is irrelevant, you can create a md5/sha1 hash from these values (besides the PageID of course). Be warned however that this table will grow really fast.
I'd advise against setting cookies for that purpose. They have a limited size and with many visited pages by the user, you could reach that limit and make the solution unreliable. Also it makes it harder to cache such page on client-side (see Cacheability), since it becomes interactive content.

You can write a django middleware and catch request.url, then setup a table with url / accesses columns. Beware of transactions for concurrent update.
If you have load problems, you can use memcached with incr or add function and periodicaly update the database table to avoid transaction locks.

Related

Django redis caching per url

So I am trying to implement moreover learn how to cache Django views per URL. I am able to do so and here is what is happening...
I visit a URL for 1st time and Django sets the caches.
I get my result from cache and not from querying the database during the second visit if the browser is same.
Now the doubt is - if I change my browser from the first visit and second visit, for example, do the first visit from Chrome (it sets the cache) and during the second visit from Mozilla, it again sets the cache. I was expecting it to return the result from the cache.
During my research on StackOverflow and checking what it sets as cache, I found there are two important things first being a header and the second being the content. And I think every time a browser is changed the header is new so it sets the cache instead of returning the result from cache. Do let me know if I am wrong.
I have a public URL and I was thinking to show data from the cache if a subsequent request is made, irrespective of browser or mobile/laptop/desktop, only based on Url, is that anyhow possible?
**(I was thinking if someone from the north part of the country visit a URL, subsequent visit to the same URL from the south part of the country should get data from the cache, based on my cache expiry time though)
Also if my understanding is wrong please correct me.
I am learning to cache using Redis on Django.
So i manually set key for some of my public url(views), adjust cache on create and delete and during get-list I check for the key values in cache, get the result from cache if cache timeout or unavailable then get the result from database. Somehow response time for this is little bit slower than cache_page(), the default django function, I dont know why. Any explanation ?? or Am i correct ?

Django multiple admin modifying the same databases

i'm a total noob in django and just wondering if it's possible for an admin doing a same thing at the same time ? the only thing i get after looking at the django documentation is that it is possible to have two admins, but is it possible for the admins to do a task in the same databases at the same time ?
thanks for any help
You didn't made it clear that what do you actually want but:
If by admin you mean a superuser then yes you can have as many admins as you want.
Admins can change anything in database at the same time, but if you mean changing a specific row of a specific table at the same time, its not possible because of these reasons:
Its kinda impossible to save something at the same time. when both admins tries to save anything, the last request will be saved (the first one will be saved too but it changes to the last request)
and if there is any important data in database, you should block any other accesses to that row till the first user has done his job and saved the changes. (imagine a ticket reservation website which has to block any other users to be allowed to order the same ticket number till user finishes the order or cancel it.)
Also if you mean 2 different django projects using a single database, then its another yes. Basically they are like 2 different admins and all above conditions works for them too.

How to get a list of all page-level APEX_ITEMS in the current page?

I have an Apex application that is quite large. The need has come up to store detailed usage logs of this application. The information on APEX_WORKSPACE_ACTIVITY_LOG is not enough, because I need to know what queries each user runs on each page.
My first thought was to get the actual Oracle query logs (V$SQL and such), but they provide no information on the user (as far as the database is concerned, all queries are made by APEX_PUBLIC_USER). I have some information about the user on V$ACTIVE_SESSION_HISTORY, but that's incomplete because it stores samples of active sessions and their SQL queries at 1-second intervals, so I miss too many queries.
So now I'm off to implementing application level logging. The "right" way to fo this would be to go through all the pages in my application and create a logging process to store the relevant information for each one (username and some page items). But I wonder if there might be something simpler that does the trick.
If I understand correcly, "application processes" are run by every page in the application. So if I can get an application process to iterate over the list of page items, I can store them all in the database and be done with it. Something like
for item in page_items {
log(username, item_name, item, date)
}
Can this be done? Or maybe the information I need is on the database already and I don't see it?
You can query the metadata tables to get all items for a specific page and then use that to get their value.
select item_name, v(item_name) item_value
from apex_application_page_items
where application_id = :APP_ID
and page_id = :APP_PAGE_ID;
That will capture all items on the page. Don't forget that if you use items on Page 0 (Global Page) you may want to query that page too.
Additionally, you may want to capture application level items too.
select item_name, v(item_name) item_value
from apex_application_items
where application_id = :APP_ID;

Global variable vs. many db queries

I will have a sidebar that appears on almost every page of my web app. The sidebar will have some drop-downs, which will consist of a total of say, 1000 different options, which are pulled from the db. Rather than doing the query to get these choices on every page load, I think it makes more sense to just do the query once, say in my config.py and store them in a variable that my views have access to. Is this OK? Is there a better way to accomplish this?
You could do that, but then you'd need to restart your Flask server every time you wanted to update the sidebar.
I'd use some other form of caching here. You could use Flask-Cache and memoize your query results. You can pick a nice long cache timeout, and then clear the cached result whenever you update the sidebar.

How to let a view has an expiration age in django?

I have certain goods for consumers to buy, let's say there are 10 limited books. Users have to submit their info forms asap to get the book.
What concerns me is, if there are say 30 people submit the form, there can only be 10 people who got the book, and the other 20s will waste there time, this harms user experience.
What I want is, I store the page open count in db, if 10 people has open the page, I will stop that view. However, what if someone just close that window and don't buy? Then the remaining books will never be sold.
How can I solve this? I am wondering if I can enable the view again if someone who opened the page didn't answer for a specific time?
You might want to implement a 2-tier system.
The first tier is the count of sold books. As soon as you have sold 10 books. The action is finished and you can deactivate the view.
To prevent more users calling the url for the offer i'd recommend you some kind if AJAX Heartbeat:
User requests url
session is set for this user and comes with a timeout, in case this user doesn't to anything for X Minutes/hours/etc. If timeout is reached: session will be deleted
offer counter is incremented by 1
javascript sends a keep alive heartbeat via ajax, so your system knows that user is still using that url and hasn't moved anywhere else.
if the heartbeat stops: delete session and decrement offer counter by 1.
this ensures that only 10 people can look at your view at a time, but you will be able to sell all 10 books.
You might want a redirect to a different page when your counter is full?
You can add some cookies to each user and save in database cookies values with page views information. And you can save user IP address to improve your system.