running a function to load csv data into the DB via Django - django

This should be like nobrainer question., but it intrigues me.
I want to load a roster of countries into the database and yes, I know I could easily do it directly by importing the csv either in mysql or postgres, and I could also write the code snippet into the console (very inconvenient) and would work fine, but I wonder how you do it in django. Because, if I have this:
def loadccountries():
with open(uploads/countries.csv) as f:
reader = csv.reader(f)
for row in reader:
_,created = countries.objects.get_or_create(
name = row[0]
)
then, where do I place that code?, in the views? if yes, then, how do I make that function alone run? I cannot see myself creating artificial urls in urls.py and an html page so that I can call the view from the URL etc. Dont vote me down, I am struggling not to go below 23 score.

You could write a custom management command which calls your loadcountries method.
This would allow you run:
manage.py loadcountries

Related

How to make filtering non model data in flask-admin

I have to make dashboard like view in flask-admin that will use data retrieved from external API. I have already written a functions that get date ranges and return data from that range. I should use BaseView probably but I don't know how to actually write it to make filters work. This is example function that i have to use: charts = generate_data_for_dashboard('164', '6423FACA-FC71-489D-BF32-3A671AB747E3', '2018-03-01', '2018-09-01'). Those params should be chosen from 3 different dropdowns. So far I know only how to render views with pre coded data like this :
class DashboardView(BaseView):
kwargs = {}
#expose('/', methods=('GET',))
def statistics_charts(self):
user = current_user
company = g.company
offices = Office.query.filter_by(company_id=company.id)
self.kwargs['user'] = user
self.kwargs['company'] = company
charts = generate_data_for_dashboard('164', '6423FACA-FC71-489D-BF32-3A671AB747E3', '2018-03-01', '2018-09-01')
self.kwargs['chart1'] = charts[0]
self.kwargs['chart2'] = charts[1]
return self.render('stats/dashboard.html', **self.kwargs)
But I need some kind of form to filter it. In addition date filter dropdown should have dynamic options : current_week, last_week, current_month, last_month, last_year. Don't know where to start.
You should use WTForms to build a form. You then have to decide if you want the data to be fetched on Submit or without a reload of the page. In the former case, you can just return the fetched information on the response page in your statistics_charts view. But if you want the data to update without a reload, you'll need to use JavaScript to track the form field changes, send the AJAX request to the API, and then interpret the resulting JSON and update your dashboard graphs and tables as needed.
I have not used it, but this tutorial says you can use Dash for substantial parts of this task, while mostly writing in Python. So that could be something to check out. There is also flask_jsondash which might work for you.

Best way to update my django model coming from an external api source?

I am getting my data through requesting an api source, then I put it in my django model. However, data update daily.. so how can I update these data without rendering it everytime?
def index (request):
session = requests.Session()
df = session.get('https://api.coincap.io/v2/assets')
response= df.json()
coin = response['data']
final_result = coin.to_dict('records')
for coin in final_result:
obj, created = Coincap.objects.update_or_create(
symbol = coin['symbol'],
name = coin['name'],
defaults = {
'price': coin['priceUsd']
})
return render(request, '/home.html/')
Right now, I have to go to /home.html , if I want my data update. However, my goal is to later serialize it and make it REST api data, so I wouldn't touch django template anymore. Anyway for it to update internally once a day after i do manage.py runserver?
For those that are looking for an example:
from django.core.management.base import BaseCommand
class Command(BaseCommand):
def handle(self,*args,**kwargs):
//Your request api here
for coin in final_result:
obj, created = Coincap.objects.update_or_create(
symbol = coin['symbol'],
name = coin['name'],
defaults = {
'price': coin['priceUsd']})
Then you run in with cron just as Nikita suggested.
One simple and common solution is to create a custom Django admin command and use Cron to run it at specified intervals. You can write a command's code to your liking and it can have access to all of the models, settings and other parts of your Django project.
You would put your code making a request and writing data to the DB, using your Django models, in your new Command class's handle() method (obviously request parameter is no longer needed). And then, if for example you have named your command update_some_data, you can run it as python manage.py update_some_data.
Assuming Cron exists and is running on the machine. Then you could setup Cron to run this command for you at specified intervals, for example create a file /etc/cron.d/your_app_name and put
0 4 * * * www-data /usr/local/bin/python /path/to/your/manage.py update_some_data >> /var/log/update_some_data.log 2>&1
This would make your update be done everyday at 04:00. If your command would provide any output, it will be written to /var/log/update_some_data.log file.
Of course this is just an example, so your server user running your app (www-data here) and path to the Python executable on the server (/usr/local/bin/python here) should be adjusted for particular use.
See links for further guidance.

Storing a .html report with a data model

I am new to Django, and I am looking for the best approach to the following problem.
I have an application that is producing two reports. One is a JSON blob so I store it in psql with data model that uses JSONField.
The second report is a .html file.
The .html file will be generated multiple times a day so the first thing that came to mind was storing it in the db.
I need to be able to pull the report as well so it can be displayed to the user in the UI.
I created a test data model using TextField:
class TestResultsHTML(models.Model):
name = models.CharField(max_length=200)
report = models.TextField()
It makes it into the Db no problem, however when I attempt to retrieve it I can't seem to get the actual report:
In [3]: html_results = TestResultsHTML.objects.get(id=4)
In [4]: html_results.name
Out[4]: 'b0f5c336-867a-44a3-a5ef-6297bf6042cf'
In [5]: html_results.report
Out[5]: "<_io.TextIOWrapper name='report.html' mode='r' encoding='UTF-8'>"
I was expected that .report would return the actual contents of the file. The file itself is 1800+ lines.
Is this a good approach or is this not the intended use of TextField?
A TextField doesn't store the file, Django has a FileField for this (see here). This saves the file to a certain location/folder and the object saved in the DB essentially stores that location which you can then access later. Something like this:
class TestResultsHTML(models.Model):
name = models.CharField(max_length=200)
file_loc = models.FileField(upload_to=upload_location)
Then open the file at a later date with something like this:
with open(html_results.file_loc, 'w'):

Django: How to insert sql statements into sqlite3 database and configure with models

I'm using Django for a project. I have a .sql file containing insert statements. How can I get them into my sqlite3 database and have them work with my models?
The project "fortune" has a models.py file that looks like the following:
class fortune(models.Model):
id = models.IntegerField(primary_key=True)
category = models.CharField(max_length=50)
length = models.IntegerField()
aphorism = models.CharField(max_length=5000)
I have a .sql file with a list of Insert statements like the follwing:
INSERT INTO "fortune_fortune" VALUES(1,'fortunes',127,'Arbitrary Text');
When I run .schema on my db.sqlite3 file which is configured with my project I see:
CREATE TABLE fortune_fortune(id integer, category varchar(50), length integer, aphorism varchar(5000));
I've tried using .read in my sqlite shell with no luck. I've tried typing "sqlite3 file.sqlite3 < file.sql" in bash as well. There is something I'm missing here, but I can't seem to ID the problem.
Thanks for your help.
ok, wait.. normally you dont use sql statements to insert data into db, if you work with django.
to insert data into db, you work with django ORM which is way much fun than these ugly sql statements.
fortune = fortune(category='new cat', length=19, aphorism='i love life')
fortune.save()
then as a result, you will have one new row in fortune table in your db. just read django docs and you feel happy!
and one more thing, class names are always in capital.
to your issue:
Django provides a hook for passing the database arbitrary SQL that’s executed just after the CREATE TABLE statements when you run migrate. You can use this hook to populate default records, or you could also create SQL functions, views, triggers, etc.
The hook is simple: Django just looks for a file called sql/<modelname>.sql, in your app directory, where <modelname> is the model’s name in lowercase.
more in docs

Huge remote source to jquery autocomplete without using database

I am working on a web app, in Django, which lets user tell their favourite movies. For the input I want to provide users a textbox with autocomplete enabled.
The list of all movies ever made is very big (18 MB) thus autocomplete has to be enabled using remote source.
To add to this, I have the constraint that I can not use a database. (Because my app is hosted on heroku and to store such data in database would cost a lot)
Right now, I have the list of all movies stored in a .py file, and I import it into my views.py. The view which handles the ajax request from autocomplete iterates over each movie in this list to filter based on the query term and returns the filtered list.
-movies.py
all_movies = [list of all movies' titles] # > 1M string elements
-views.py (handle_autocomplete() gets called whenever user changes the input in the textbox on web app)
import movies
def handle_autocomplete(request):
data = request.GET['term']
my_list = [title for title in movies.all_movies if data in title]
return HttpResponse(simplejson.dumps(my_list))
What are the disadvantages of this approach and how can I improve upon it?
Are there any libraries/ django apps which handle remote-source autocomplete ?