Biopython Entrez wanting to access /root/.config in Django app - django

I have some code in a Django app which does the following, to get a Pubmed article by DOI:
def getPubmedByDOI(request,doi):
Entrez.email = 'me#mydomain.com'
handle = Entrez.esearch(db="pubmed", term=doi)
record = Entrez.read(handle)
return getPubmedArticle(request,record["IdList"][0]) // renders the article
This works nicely but for one thing - the Entrez.esearch call insists upon access to /root/.config on the server, specifically to write to the following empty directory:
/root/.config/biopython/Bio/Entrez/DTDs/
It's Apache on Gentoo, running as follows:
User django
Group apache
All the code for the application is in ~django/, so I'd expect any writing to be in ~django/.config rather than /root/.config. I can work around this by changing permissions on /root but a better solution would be to configure Biopython or Apache so as not to write to /root. Does anyone have any suggestions as to how this might be done?

Logged upstream as https://github.com/biopython/biopython/issues/918 which suggests setting:
>>> from Bio.Entrez.Parser import DataHandler
>>> DataHandler.global_dtd_dir
'/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/Bio/Entrez/DTDs'
>>> DataHandler.local_dtd_dir = '...'

Related

Django - Query_set returns an empty arraylist when it is ran in the test

I am trying to run a TestCase on my model.
I already have a MySQL database (specifically MariaDB through a HeidiSQL GUI) created and connected with the respective data inside for this project.
My test.py code is as follows:
class TestArrivalProbabilities(TestCase):
def test_get_queryset_test(self):
print("Hello Steve!")
i = 1
self.assertEqual(i, 1)
l = [3, 4]
self.assertIn(4, l)
def test_get_queryset_again(self):
query_set = ArrivalProbabilities.objects.all()
print(query_set)
n = len(query_set)
print(n) # Print each row
bin_entries = []
bin_edges = []
for i in range(n):
print(query_set[i])
if query_set[i].binEntry is not None:
bin_entries.append(query_set[i].binEntry)
bin_edges.append(query_set[i].binEdge)
print(bin_entries, bin_edges)
hist = (numpy.array(bin_entries), numpy.array(bin_edges))
However, the output in the terminal is this:
(venv) C:\Users\Steve\uni-final-project>python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
<QuerySet []>
0
[] []
.Hello Steve!
.
----------------------------------------------------------------------
Ran 2 tests in 0.016s
OK
Destroying test database for alias 'default'...
I have tried to figure out why the MySQL database I built isn't being used. I read up that Django creates a Test 'dummy database' to use on a test and then tears it down after but am I missing something really obvious?
I don't think it is a connection issue as I have pip installed mysqlclient. And I have tried to use the https://docs.djangoproject.com/en/3.2/topics/db/queries/#creating-objects but I still get the same result.
I have read the documentation but I am struggling with certain aspects of it as I am new to software development and this course is quite a steep learning curve.
I checked to see if this question wasn't asked before but I couldn't see any answers to it. Apologies in advance if it has been answered somewhere.
Any help in the right direction or a solution is much appreciated.
Thanks.
First of all you should read something related to testing not django's creating-objects. When you want to test your code usually there are some approaches regarding database. In official django documentation its shows how to deal with database instances. Simply when you start your test it creates a test database and runs your testcases. For that you can use a setUp function
add this and try again please:
class TestArrivalProbabilities(TestCase):
def setUp(self):
....
ArrivalProbabilities.objects.create(...)
ArrivalProbabilities.objects.create(...)
....
after this part you no longer will see empty queryset.
You can also use fixtures

Flask - Generated PDF can be viewed but cannot be downloaded

I recently started learning flask and created a simple webapp which randomly generates kids' math work sheets in PDF based on user input.
The PDF opens automatically in a browser and can be viewed. But when I try downloading it both on a PC and in Chrome iOS, I get error messages (Chrome PC: Failed - Network error / Chrome iOS:the file could not be downloaded at this time).
You can try it out here: kidsmathsheets.com
I suspect it has something to do with the way I'm generating and returning the PDF file. FYI I'm using ReportLab to generate the PDF. My code below (hosted on pythonanywhere):
from reportlab.lib.pagesizes import A4, letter
from reportlab.pdfgen import canvas
from reportlab.platypus import Table
from flask import Flask, render_template, request, Response
import io
from werkzeug import FileWrapper
# Other code to take in input and generate data
filename=io.BytesIO()
if letter_size:
c = canvas.Canvas(filename, pagesize=letter)
else:
c = canvas.Canvas(filename, pagesize=A4)
pdf_all(c, p_set, answer=answers, letter=letter_size)
c.save()
filename.seek(0)
wrapped_file = FileWrapper(filename)
return Response(wrapped_file, mimetype="application/pdf", direct_passthrough=True)
else:
return render_template('index.html')
Any idea what's causing the issue? Help is much appreciated!
Please check whether you are using an ajax POST request for invoking the endpoint to generate your data and display the PDF respectively. If this is the case - quite probably this causes the behaviour our observe. You might want to try invoking the endpoint with a GET request to /my-endpoint/some-hashed-non-reusable-id-of-my-document where some-hashed-non-reusable-id-of-my-documentwill tell the endpoint which document to serve without allowing users to play around with guesstimates about what other documents you might have. You might try it first like:
#app.route('/display-document/<document_id>'):
def display_document(document_id):
document = get_my_document_from_wherever_it_is(document_id)
binary = get_binary_data_from_document(document)
.........
Prepare response here
.......
return send_file(binary, mimetype="application/pdf")
Kind note: a right click and 'print to pdf' will work but this is not the solution we want

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.

running a function to load csv data into the DB via 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

Does django-constance admin supports database backend?

I'm trying to setup the admin to show settings meant to be stored in database backend (Postgres 9.5.0). I manually created values in shell_plus as follows:
In [1]: from constance.backends.database.models import Constance
In [2]: first_record = Constance.objects.get(id=1)
In [3]: first_record
Out[3]:
pg-admin properly shows the entry although django admin doesn't show it at all. I ran migrate command for both databases (I have default and product databases) but the record still is not showing up. Certainly I can make it work with forcing to register with admin as follows:
admin.site.register(Constance)
but my question is if it's necessary?
Yes, they do.
You need to manage dependencies, but you can just use next command to install:
pip install "django-constance[database]"
Also you need to add some additionl settings to your settings.py :
CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
INSTALLED_APPS = (
# other apps
'constance.backends.database',
)
#optional - in case you want specify table prefix
CONSTANCE_DATABASE_PREFIX = 'constance:myproject:'
Then you need to apply migrations by running command python manage.py migrate database
For displaying settings inputs in admin you should specify them in your settings.py. There are various types of fields and you even can add your own types of fields using CONSTANCE_ADDITIONAL_FIELDS parameter.
CONSTANCE_CONFIG = {
'THE_ANSWER': (42, 'Answer to the Ultimate Question of Life, '
'The Universe, and Everything'),
}
You can read more at documentation page.