'list' object has no attribute 'json' - django

I'm trying to fetch all the products from the firebase database, but in the json data form.
Here's the structure of my database:
products{
0{
name:...
price:...
}
1{
name:..
price:..
and so on. And below is the code I tried:
import json
from .models import Product
import pyrebase
def get_products():
database = firebase_key().database()
product_list = Product.objects.all()
r = database.child("products").get().each()
jsonList = r.json()
jsonData = jsonList['products']
data = []
for products in r:
productData = {}
productData['name'] = products.name
productData['image'] = products.image
productData['price'] = products.price
productData['description'] = products.description
data.append(productData)
return data
I'm new to both django and firebase, so any help would be appreciated

As #Kevin pointed out the each does not return a json, but a list. You can check it out on the pyrebase documentation.
Your code should probably look like this:
all_products = database.child("products").get()
for product in all_products.each():
data.append(product.val()) # This works if your fields have the same names.
Edit
If you still need data as a JSON.
json_data = json.dumps(data)

Related

how to serialize data with python after getting it from firebase in django?

i'm working with Django and i want to retrieve data from firebase and make it readable and serializable
when retrieving data from the default database (sqlite) i use this function :
#api_view([('GET')])
def getPatients(request):
patients = Patient.objects.all()
serializer = PatientSerializer(patients , many = True)
return Response(serializer.data)
i want to change this function to get and serialize the data from firebase .
i tried to get data from firebase and send it in the response but it is not showing in the web view page .
the solution i tried :
#api_view([('GET')])
def getPatients(request):
patients = database.child('patients').get().val()
serializer = PatientSerializer(patients , many = True)
return Response(serializer.data)
It sounds like you are trying to get data from Firestore.
If that is the case you need to initialize firestore and convert the data into a python dictionary using the to_dict() method.
secret = os.getenv("FIREBASE_ADMIN_SDK")
cred = credentials.Certificate(json.loads(secret))
firebase_app = initialize_app(cred)
db = firestore.client()
doc_ref = db.collection('<your_collection').doc('<your_document>')
patients = doc_ref.get().to_dict()
this solution worked for me :
#api_view([('GET')])
def getPatients(request):
# patients = Patient.objects.all()
# serializer = PatientSerializer(patients , many = True)
patients = [] # make empty list for patients
patientsData = database.child('patients').get().val() #get all the value from firebase database
for patient in patientsData : # fill the patients list
print(database.child('patients').child(patient).get().val())
patients.append(database.child('patients').child(patient).get().val())
print(patients)
return Response(patients) # send it to the api

Flask app-builder how to make REST API with file items

I'm making a REST api that files can be uploaded based in MODEL-VIEW in flask-appbuilder like this.
But I don't know how to call REST API (POST /File).
I tried several different ways. but I couldn't.
Let me know the correct or the alternative ways.
[client code]
file = {'file':open('test.txt', 'rb'),'description':'test'}
requests.post(url, headers=headers, files=file)
==> Failed
model.py
class Files(Model):
__tablename__ = "project_files"
id = Column(Integer, primary_key=True)
file = Column(FileColumn, nullable=False)
description = Column(String(150))
def download(self):
return Markup(
'<a href="'
+ url_for("ProjectFilesModelView.download", filename=str(self.file))
+ '">Download</a>'
)
def file_name(self):
return get_file_original_name(str(self.file))
view.py
class FileApi(ModelRestApi):
resource_name = "File"
datamodel = SQLAInterface(Files)
allow_browser_login = True
appbuilder.add_api(FileApi)
FileColumn is only a string field that saves the file name in the database. The actual file is saved to config['UPLOAD_FOLDER'].
This is taken care of by flask_appbuilder.filemanager.FileManager.
Furthermore, ModelRestApi assumes that you are POSTing JSON data. In order to upload files, I followed Flask's documentation, which suggests to send a multipart/form-data request. Because of this, one needs to override ModelRestApi.post_headless().
This is my solution, where I also make sure that when a Files database row
is deleted, so is the relative file from the filesystem.
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder.api import ModelRestApi
from flask_appbuilder.const import API_RESULT_RES_KEY
from flask_appbuilder.filemanager import FileManager
from flask import current_app, request
from marshmallow import ValidationError
from sqlalchemy.exc import IntegrityError
from app.models import Files
class FileApi(ModelRestApi):
resource_name = "file"
datamodel = SQLAInterface(Files)
def post_headless(self):
if not request.form or not request.files:
msg = "No data"
current_app.logger.error(msg)
return self.response_400(message=msg)
file_obj = request.files.getlist('file')
if len(file_obj) != 1:
msg = ("More than one file provided.\n"
"Please upload exactly one file at a time")
current_app.logger.error(msg)
return self.response_422(message=msg)
else:
file_obj = file_obj[0]
fm = FileManager()
uuid_filename = fm.generate_name(file_obj.filename, file_obj)
form = request.form.to_dict(flat=True)
# Add the unique filename provided by FileManager, which will
# be saved to the database. The original filename can be
# retrieved using
# flask_appbuilder.filemanager.get_file_original_name()
form['file'] = uuid_filename
try:
item = self.add_model_schema.load(
form,
session=self.datamodel.session)
except ValidationError as err:
current_app.logger.error(err)
return self.response_422(message=err.messages)
# Save file to filesystem
fm.save_file(file_obj, item.file)
try:
self.datamodel.add(item, raise_exception=True)
return self.response(
201,
**{API_RESULT_RES_KEY: self.add_model_schema.dump(
item, many=False),
"id": self.datamodel.get_pk_value(item),
},
)
except IntegrityError as e:
# Delete file from filesystem if the db record cannot be
# created
fm.delete_file(item.file)
current_app.logger.error(e)
return self.response_422(message=str(e.orig))
def pre_delete(self, item):
"""
Delete file from filesystem before removing the record from the
database
"""
fm = FileManager()
current_app.logger.info(f"Deleting {item.file} from filesystem")
fm.delete_file(item.file)
You can use this.
from app.models import Project, ProjectFiles
class DataFilesModelView(ModelView):
datamodel = SQLAInterface(ProjectFiles)
label_columns = {"file_name": "File Name", "download": "Download"}
add_columns = ["file", "description", "project"]
edit_columns = ["file", "description", "project"]
list_columns = ["file_name", "download"]
show_columns = ["file_name", "download"]
Last add the view to the menu.
appbuilder.add_view(DataFilesModelView,"File View")

Django WeasyPrint - Export filtered list

So I've created a pdf file from a ListView called "OrderListView". Now I would like to pass a queryset to the pdf file.
I rewrote my listview as a function view for more clarity. I need to find a way to pass the queryset to the pdf view. I'm using django-filter to create the filtered view. I have the following;
filters.py
class OrderFilter(django_filters.FilterSet):
class Meta:
model = Order
fields = {
'start_date': ['gte'],
'end_date': ['lte'],
}
views.py
from .filters import *
# View to show a filtered list using django-filter
def order_list(request):
order_list = Order.objects.all()
order_filter = OrderFilter(request.GET, queryset=order_list)
start_date__gte = request.GET.get('start_date__gte','')
start_date__lte = request.GET.get('start_date__lte','')
return render(request, 'orders/order_list.html', {
'filter': order_filter,
'start_date__gte': start_date__gte,
'start_date__lte': start_date__lte,
})
# View to create a pdf file from the filtered view using WeasyPrint
def order_list_pdf(request):
# Edited: Create queryset
start_date__gte = request.GET.get('start_date__gte','')
start_date__lte = request.GET.get('start_date__lte','')
order_list = Order.objects.filter(
Q(start_date__gte=start_date__gte) |
Q(start_date__lte=start_date__lte)
)
order_filter = OrderFilter(request.GET, queryset=order_list)
response = HttpResponse(content_type="application/pdf")
response['Content-Inline'] = 'attachment; filename=filtered_list.pdf'.format()
html = render_to_string('pdf/pdf_booking_list_arrivals.html', {
'filtered_list': order_list,
})
font_config = FontConfiguration()
HTML(string=html).write_pdf(response, font_config=font_config)
return response
So I have tried using
start_date__gte = request.GET.get('start_date__gte','')
start_date__lte = request.GET.get('start_date__lte','')
And pass the query with the url
#edited
<a class="btn" href="{% url 'order_list_pdf' %}?start_date__gte={{ start_date__gte }}&start_date__lte={{ start_date__lte }}">Create PDF</a>
This does create the query in the url but does not filter the list. The generated pdf is working, I just need to find a way to only send the filtered results to the pdf view.
Any help would be appreciated!

Update Existing Document : Mongo Alchemy

I need some help with MongoAlchemy. I'm trying to create a web application with python, flask, Mongo DM and Mongo Alchemy (as an object document mapper) and I'm struggling with updating existing documents.
My problem is that I cannot update an existing document through it's object Id. Below I'm attaching my def for updating
#app.route('/update', methods =[ 'GET', 'POST' ])
def update():
if request.method == 'POST':
id = request.form['object_id'] # Getting values with html
patientzero = BloodDoonor.query.get_or_404(id)
first_name = request.form['name']# Getting values with htmlform
last_name = request.form['surname']# Getting values with html form
blood_type = request.form['blood_type']# Getting values with html
update_record = BloodDoonor.patientzero.update(BloodDoonor.last_name = last_name)
return render_template('update.html', result = result)
And flask gives me that error:
AttributeError AttributeError: type
object 'BloodDoonor' has no attribute 'patientzero'
I'm very new to Python and not very good in code. Please forgive me for the sloppy description I gave above. Any help would be appreciated.
To update an existing document just change the value of the object which you queried from db with form values and then just save that object:
#app.route('/update', methods =[ 'GET', 'POST' ])
def update():
if request.method == 'POST':
id = request.form['object_id']
patientzero = BloodDoonor.query.get_or_404(id)
patientzero.first_name = request.form['name']
patientzero.last_name = request.form['surname']
patientzero.blood_type = request.form['blood_type']
patientzero.save()
return render_template('update.html')

DJANGO simplejson

Good afternoon..i have a model with a class like this:
class Reportage:
def get_num(self):
end_date = self.date.end_date
start_date = self.date.start_date
duration = time.mktime(end_date.timetuple()) - time.mktime(start_date.timetuple())
delta_t = duration / 60
num = []
for t in range(0,duration,delta_t):
start = t + start_date
end = datetime.timedelta(0,t+delta_t) + start_date
n_num = self.get_num_in_interval(start,end)
num.append([t, n_num])
return num
I want to serialize with simplejson the array num [] in the views.py for passing in a second moment this array to a jquery script to plot it in a graph..
what's the code to serialize that array..?
I hope I was clear .. thanks in advance to all those who respond ..
Following #ninefingers' response. I think that your question is aimed on how to make that dumped json string available to a jQuery plugin.
# views.py
def my_view(request):
# do stuff
num = reportage_instance.get_num()
num_json = simplejson.dumps(num)
return render(request, 'template.html', {
'num_json': num_json,
})
In your template, you make available that json obj as a Javascript variable
# template.html
<html>
<body>
<script>
var NUM_JSON = {{num_json|safe}};
myScript.doSomething(NUM_JSON);
</script>
</body>
</html>
Now you can call regular JS with the NUM_JSON variable.
If you're looking to do this in a model, something like this would work:
# if this were a models.py file:
import simplejson
# other django imports:
class SomeModel(models.Model):
property = models.SomeField()...
def some_function(self):
num = []
# full num
simplejson.dumps(num)
That'll dump num to a string-representation of the json, which you can then return, or write to a file, and so on.
From a view you have a choice - but if your view is an ajax view returning some json for processing you might do this:
# views.py
# ...
def my_ajax_call(request, model_pk):
try:
mymodel = SomeModel.get(pk=model_pk)
except SomeModel.NotFoundException as e:
return HttpResonse("Unknown model", status=404)
else:
return HttpResponse(mymodel.some_function()) # returns simplejson.dumps(num)
This can then be used from a template in Javascript - the other answer shows you how you might approach that :)