how continuously run function on page request - django

I want to use third party's REST API providing real-time foreign exchange rates in my django app which should continuously show changing exchange rates.
my code works but only on every page reload. but I want my code to be running continuously and showing exchange rate on page even if the page is not reloaded.
def example(request)
RATE__API_URL = 'REST API url'
while True
rate = requests.get(RATE__API_URL).json()
b = rate['rates']['EURUSD']['rate']
context = {'b': b}
return render(request, 'example.html', context)
on my example.html
<h1>
{{b}}
</h1>
code is running and does not show any errors

There are a few ways you can solve your requirement and none of them are the "right way", also much of it depends of what you have in your code, so I'll try to lay them out for you, and given the extent of what needs to be done while providing some links so you can work on it, but I will not give code because you'll require a fair amount of tailored code (sorry for that) and the references are good enough for you to develop your own solution.
The first thing you have to keep in mind is than you'll need to solve two really big and really different requirements:
The first part of your solution is retrieving the data from the source in a timely manner. The second part is to have a way to update the data in the template without the need for the user to reload the page.
To retrieve the data you said you already have an API where you'll get the data, but your code is not an efficient way to approach this, and it also may generate a risk because it is prone to hit too many times the API server; the best way I can think of would be if the API has webhooks or push notifications to which you can subscribe (which I doubt), the second best choice is to implement a Celery task, that way you will be calling the data regularly, and you'll not eat the API service resources.
With the first part out of the way, what you have left to do is to implement a way to call regularly from the UI for the newest data. Perhaps the simplest way to solve it is to implement an asynchronous call with Javascript/JQuery embedded in a script inside your template, but remember:
For this to work you'll need a model to store the data (If you don't
have an use for historic data, then just keep the most recent
one).
You'll need a view that exposes the data to your UI call (one that sends a JSON)
Another solution is to implement websockets, and the best way to achieve this for Django is using django-channels. You'll have to implement two main things:
In the backed you need to define the consumers flow so you can send
the data to the UI.
In the template you need to implement the websocket connection and a way to handle the updating part of the data for the user.
If you choose this way, and given than you don't need historic data, you can obviate the model and go straight from the Celery task to the UI through the consumer.

Related

Best Practice Using Django Signal (For user authentication?)

I am new to Django and want to know deeper about the concept of signals.
I know how it works but really don't understand when should one really use it.
From the doc it says 'They’re especially useful when many pieces of code may be interested in the same events.'
What are some real applications that use signals for its advantage?
e.x. I'm trying to make a phone verification after user signup. Because it can be integrated inside the single app and the event that interested for the signal is only this 'verify' function, therefore I don't really need signal. I can just pass the information from one view to the other, rather than using pre_save signal from the registration.
I'm sorry if my question is kind of basic. But I really want to know some insight what is the real application, in which many codes interested in one particular event and what are some trade off in my application.
Thanks!!
Often signals is used when you need to do some database-specific low-level stuff. For example, if you use ElasticSearch for better searching documents on your site, you may want to automatically update search indexes, when new document is created or old one was edited.
Also you may have some complex logic of managing database objects. For example, you may need some specific logic of deleting object. For example, when user is deleted, you may want change all the links to his profile by some placeholder, or when new message is created or other action is performed by user, you want to update "last visited" field in user's profile and there's no direct relation between this action and updating the profile.
But when you're just implementing business-logic as in your example with verification, you don't need to use signals, because you don't need any universal logic related to deleting/creating/editing any object: you have a certain object with which you work and can do stuff directly.

django-channels: keeping track of users in "rooms"

TL;DR - How do I maintain a list of users in each room so that I can send that data to the front-end to display a list of participants in this room.
I'm designing a collaborative web application that uses django-channels for websocket communication between the browser and the server. A room can be joined by more than one user and every user should be aware of every other user in the room. How would I go about achieving this using django-channels (v2)?
I already went through the documentation and a few example projects available online but none of them have added a similar functionality. I also know about django-channels-presence but the project doesn't seem to be actively maintained so I didn't really bother looking into examples using that.
Here's what I've come up with so far:
- For every room, I create an object in the database and those objects can keep track of the users that are in the room. So for e.g in the WS consumer's connect() method I could do a get_or_create_room() call and room.add_participant(self.user_name) (or fetch this from the scope) and in the disconnect() method I could remove myself from the room. The problem with this, however, is that I might end up creating race conditions? I think? Also since I'm fetching objects from the ORM, I have to make sure that every time, before using this object I have to re-fetch it from the DB because it can (and will) become outdated quickly. This doesn't seem ideal at all.
- Another way I can think of is attaching data to self.channel_layer in the consumer where I can do something like setattr(self.channel_layer, f'users_{room_id}', {}) and maintain this dictionary for every user entering and leaving. This again doesn't sound very safe and I didn't see anyone using this so I'm unsure.
Any help regarding this would be appreciated. I'd also like to be able to see how existing applications do this if anyone can point me to one?
so in short there is no way to ask channels for the members in a group so you either need to:
Write some info into the db, with a timestamp so that you can see if it is old
or
send a message every (n seconds) over the channel group (machine readable item with the users id) then your consumers (or frontend) can maintain a list of users and filter this to those that have a resent timestamp. The disadvantage here is it might take a few seconds to detect all the users in a chat room.
You can't do anything like writing to a dict or global object since this is not shared over all the consumers.

How to prevent a Django view that calls an external api from being flooded when it is called by a GET request?

I am writing a Django application with a view that is passed GET parameters. This view contacts an external API to get information, and passes the consolidated information to a template. The external API call is costly and limited. I am concerned that in a production environment, an attacker could write a script to repeatedly load the page with different parameters, (as I'm caching requests, so repeated calls with same parameters are fine), to exhaust my ability to use the external API.
I am trying to ensure that only humans can load my view (or specifically, reach the point of the external API call), or, at least, that a robot can't load it hundreds of times.
The most elegant solution would be some code in the view before the API call that could validate the user somehow. If the user failed the validation, they could be referred to another view or to a different template with a failure message. I am trying to do this as elegantly as possible and not be sloppy, however, so I'm looking for advice on best practice.
Initially, I intuitively wanted to use reCAPTCHA, however, it seems that this is generally used for forms. Adding reCaptcha to the form that directs to this page would not solve my problem, since the attacker could just run the attack by modifying the parameters in the url. Is there a way, either properly or with a hack, to test the user with an invisible, (or possibly visible, but I don't want to deter people by making them fill out a captcha every time), re-captcha in the view? I can't think of a way to do this, but perhaps it's possible.
Hopefully there is some external service or library that I could use to make a simple call to some sort of validator, which at least will block or heavily throttle a user if they are spamming my site, and, at best, would use more sophisticated methods to tell.
The view structure:
def myView(request,query1,query2):
results = call_external_api(query1, query2)
return results to a template using context
Thanks for the help in advance, I hope I was clear in describing my problem!

How to use reddit api in Django?

Is this even possible? Where should I put a code for it? In views.py or stand-alone file? However deserializing a json/xml could be an option but I dont know where and how to put it
It's definitely possible, depending on how strictly you're thinking of the "latest post".
You could put the API reader in it's own file (reddit.py) and call the reader when a user GETs your page, then populate the template with the results from the reader.
Or even better, if it doesn't need to be the absolute latest post, you could store the latest post at a specific point in time (e.g., every 15 minutes) in a database, and then get the relevant object from your model when the user GETs your page. This will likely be much faster than making a live API call and parsing the result while your page loads. You can have the reader asynchronously call the Reddit API every 15 minutes so it doesn't impact the user's experience.

Application logic in view code

Should I be writing application logic in my view code? For example, on submission of a form element, I need to create a user and send him an activation email. Is this something to do from a view function, or should I create a separate function to make it easier to test down the road? What does Django recommend here?
I found it very hard to figure out where everything goes when I started using django. It really depends on the type of logic you are writing.
First start with the models: model-methods and managers are a good place to perform row-level logic and table level logic i.e. a model manager would be a good place to write code to get a list of categories that are associated with all blogposts. A model method is a good place to count the characters in a particular blogpost.
View level logic should deal with bringing it all together - taking the request, performing the necessary steps to get to the result you need (maybe using the model managers) and then getting it ready for the template.
If there is code that doesn't fit in else where, but has a logical structure you can simply write a module to perform that. Similarly if there are scraps of code that you don't think belong, keep a utils.py to hold them.
You shouldn't perform any logic really in your templates - instead use template tags if you have to. These are good for using reusable pieces of code that you you neither want in every request cycle nor one single request cycle - you might want them in a subset (i.e. displaying a list of categories while in the blog section of your website)
If you do want some logic to be performed in every request cycle, use either context processors or middleware. If you want some logic to be performed only in one single request cycle, the view is probably the place.
TLDR: Writing logic in your view is fine, but there are plenty of places that might be more appropriate
Separating the registration code into it's own function to make testing easier is a good reason. If you allowed admins to register users in a separate, private view, then a registration function would be more DRY. Personally, I don't think a little application logic in the code will do to much harm.
You might find it instructive to have a look at the registration view in the django-registration app -- just to see how it's written, I'm not saying you should or have to use it. It has encapsulated the user registration into it's own function (there's a level of indirection as well, because the registration backends are pluggable).