How to get related resource? - tastypie

I have models:
class Article(models.Model):
name = models.CharField(max_length=255)
symbol = models.CharField(max_length=255, unique=True)
. . .
def __unicode__(self):
return '%s (%s)' % (self.name, self.symbol)
class ArticleRel(models.Model):
active = models.BooleanField(default=True)
create = models.DateTimeField(default=datetime.now)
article = models.ForeignKey(Article)
. . .
def __unicode__(self):
return '%s' % (self.id)
and resources:
class ArticleResource(ModelResource):
owner = fields.ForeignKey(UserResource, 'owner')
class Meta:
queryset = Article.objects.all()
resource_name = 'articles'
serializer = Serializer()
authorization = Authorization()
filtering = {
'owner': ALL_WITH_RELATIONS,
}
always_return_data = True
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<id>\d+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
class ArticleRelResource(ModelResource):
article = fields.ForeignKey(ArticleResource, 'article')
class Meta:
queryset = ArticleRel.objects.all()
resource_name = 'article_rels'
serializer = Serializer()
authorization = Authorization()
filtering = {
'article': ALL_WITH_RELATIONS,
}
always_return_data = True
def prepend_urls(self):
return [
url(r"^(?P<resource_name>%s)/(?P<id>\d+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"),
]
and now: how to set this resources so as to get articles with all article_rels in one query?

I'm not sure I understood the question.
If you meant you wanted to get both article_rels and articles, you can use full=true in the foreign key field.
article = fields.ForeignKey(ArticleResource, 'article', full=True)
as stated in the documentation - http://django-tastypie.readthedocs.org/en/latest/fields.html#full
Keep in mind of the overhead time of the extra db queries.

This work for me:
def dehydrate(self, bundle):
bundle.data['rels'] = [ar.__dict__ for ar in ArticleRel.objects.filter(article__id=bundle.data['id'])]
return bundle

Related

FastAPI Pytest why does client returns 422

I'm trying to implement testing my post route. It works in my project. I have problems only with pytest.
main.py:
#app.post('/create_service', status_code=status.HTTP_201_CREATED)
async def post_service(
response: Response, service: CreateService, db: Session = Depends(get_db)
):
service_model = models.Service()
service_name = service.name
service_instance = db.query(models.Service).filter(
models.Service.name == service_name
).first()
if service_instance is None:
service_model.name = service_name
db.add(service_model)
db.commit()
serviceversion_model = models.ServiceVersion()
service_instance = db.query(models.Service).filter(
models.Service.name == service_name
).first()
serviceversion_instance = db.query(models.ServiceVersion).filter(
models.ServiceVersion.service_id == service_instance.id
).filter(models.ServiceVersion.version == service.version).first()
if serviceversion_instance:
raise HTTPException(
status_code=400, detail='Version of service already exists'
)
serviceversion_model.version = service.version
serviceversion_model.is_used = service.is_used
serviceversion_model.service_id = service_instance.id
db.add(serviceversion_model)
db.commit()
db.refresh(serviceversion_model)
service_dict = service.dict()
for key in list(service_dict):
if isinstance(service_dict[key], list):
sub_dicts = service_dict[key]
if not sub_dicts:
response.status_code = status.HTTP_400_BAD_REQUEST
return HTTPException(status_code=400, detail='No keys in config')
servicekey_models = []
for i in range(len(sub_dicts)):
servicekey_model = models.ServiceKey()
servicekey_models.append(servicekey_model)
servicekey_models[i].service_id = service_instance.id
servicekey_models[i].version_id = serviceversion_model.id
servicekey_models[i].service_key = sub_dicts[i].get('service_key')
servicekey_models[i].service_value = sub_dicts[i].get('service_value')
db.add(servicekey_models[i])
db.commit()
return 'created'
test_main.py:
def test_create_service(client, db: Session = Depends(get_db)):
key = Key(service_key='testkey1', service_value='testvalue1')
service = CreateService(
name="testname1",
version="testversion1",
is_used=True,
keys=[key, ]
)
response = client.post("/create_service", params={"service": service.dict()})
assert response.status_code == 200
I tried to post service as json, as CreateService instance and finally as params dictionary. I have no errors at response line only with the last one . But I got 422 response status code. What is wrong?
If it can help:
schemas.py
class Key(BaseModel):
service_key: str
service_value: str
class CreateService(BaseModel):
name: str
version: str
is_used: bool
keys: list[Key]
class Config:
orm_mode = True
Don't use params. Use json:
response = client.post("/create_service", json=service.dict())

object has no attribute 'dlg'

I'm trying to create a plugin for a Uni-subject which will receive a zipcode from a user and return the name of the corresponding location.
I have created the plugin layout, through the Plugin Builder and have designed the graphical interface with QtDesigner https://i.stack.imgur.com/h6k6Q.png . I have also added the .txt file that contains the zipcodes database to the plugin folder.
However, when I reload the plugin it gives me the error "object has no attribute 'dlg'" error message
Could you give me some guidance here and point me to where the problem could be? I am new to plugin development and python. Thanks
The code is this one:
import os
import sys
import qgis.core
from qgis.PyQt import uic
from qgis.PyQt import (
QtCore,
QtWidgets
)
import geocoder
# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'example_dialog_base.ui'))
class ExampleDialog(QtWidgets.QDialog, FORM_CLASS):
POSTAL_CODES_PATH = ":/plugins/example/todos_cp.txt"
def __init__(self, parent=None):
"""Constructor."""
super(ExampleDialog, self).__init__(parent)
# Set up the user interface from Designer through FORM_CLASS.
# After self.setupUi() you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots - see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)
#self.QpushButton.clicked.connect(self.print_hello_world)
self.QlineEdit.textChanged.connect(self.toggle_find_button)
self.find_code_btn.clicked.connect(self.execute)
#def print_hello_world(self):
#print('Hello World!')
def toggle_find_button(self):
if self.QlineEdit.text() == "":
self.find_code_btn.setEnabled(False)
else:
self.find_code_btn.setEnabled(True)
def find_record(self, main_code, extension):
file_handler = QtCore.QFile(self.POSTAL_CODES_PATH)
file_handler.open(QtCore.QIODevice.ReadOnly)
stream = QtCore.QTextStream(file_handler)
while not stream.atEnd():
line = stream.readLine()
info = line.split(";")
code1 = info[-3]
code2 = info[-2]
if code1 == main_code and code2 == extension:
result = info
break
else:
raise RuntimeError("Sem resultados")
return result
def handle_layer_creation(self, record):
place_name = record[3]
point = geocode_place_name(place_name)
print("lon: {} - lat: {}".format(point.x(), point.y()))
layer = create_point_layer(
point,
f"found_location_for_{record[-3]}_{record[-2]}",
place_name
)
current_project = qgis.core.QgsProject.instance()
current_project.addMapLayer(layer)
def show_error(self, message):
message_bar = self.iface.messageBar()
message_bar.pushMessage("Error", message, level=message_bar.Critical)
def validate_postal_code(raw_postal_code):
code1, code2 = raw_postal_code.partition("-")[::2]
if code1 == "" or code2 == "":
raise ValueError(
"Incorrect postal code: {!r}".format(raw_postal_code))
return code1, code2
def geocode_place_name(place_name):
geocoder_object = geocoder.osm(place_name)
lon = geocoder_object.json.get("lng")
lat = geocoder_object.json.get("lat")
if lat is None or lon is None:
raise RuntimeError(
"Could not retrieve lon/lat for "
"place: {!r}".format(place_name)
)
point = qgis.core.QgsPointXY(lon, lat)
return point
def create_point_layer(point, layer_name, place_name):
layer = qgis.core.QgsVectorLayer(
"Point?crs=epsg:4326&field=address:string(100)",
layer_name,
"memory"
)
provider = layer.dataProvider()
geometry = qgis.core.QgsGeometry.fromPointXY(point)
feature = qgis.core.QgsFeature()
feature.setGeometry(geometry)
feature.setAttributes([place_name])
provider.addFeatures([feature])
layer.updateExtents()
return layer

How to use database models in Python Flask?

I'm trying to learn Flask and use postgresql with it. I'm following this tutorial https://realpython.com/flask-by-example-part-2-postgres-sqlalchemy-and-alembic/, but I keep getting error.
Cannot import name 'AorticStenosis' from partially initialized module 'models' (most likely due to a circular import)
I understand the problem, but I can't figure out how to fix it. So, I started playing around and try to use the steps by step tutorial on something that I'm working on, but I still get the same problem.
Here's my attempt:
Models.py
from app import db
class AorticStenosis(db.Model):
__tablename__ = 'wvu-model'
id = db.Column(db.Integer, primary_key=True)
ip_address = db.Column(db.String())
date_created = db.Column(db.DateTime, default=datetime.utcnow)
e_prime = db.Column(db.Float())
LVMi = db.Column(db.Float())
A = db.Column(db.Float())
LAVi = db.Column(db.Float())
E_e_prime = db.Column(db.Float())
EF = db.Column(db.Float())
E = db.Column(db.Float())
E_A = db.Column(db.Float())
TRV = db.Column(db.Float())
prediction = db.Column(db.String())
def __init__(self, ip_address, e_prime, LVMi, A, E_e_prime, EF, E, E_A, TRV, prediction):
print('initialized')
self.ip_address = ip_address
self.e_prime = e_prime
self.LVMi = LVMi
self.A = A
self.LAVi = LAVi
self.E_e_prime = E_e_prime
self.EF = EF
self.E = E
self.E_A = E_A
self.TRV = TRV
self.prediction = prediction
def __repr__(self):
return '<id {}>'.format(self.id)
app.py
import os
import ast
import bcrypt
from flask import Flask, redirect, render_template, request, session, url_for
import flask_login
from flask_sqlalchemy import SQLAlchemy
from bigml.deepnet import Deepnet
from bigml.api import BigML
import pickle as pkl
import sklearn
app = Flask(__name__)
if app.config['ENV'] == 'production':
app.config.from_object('as_config.ProductionConfig')
else:
app.config.from_object("config.DevelopmentConfig")
# app.config.from_pyfile('as_config.py')
# app.config.from_object(os.environ['APP_SETTINGS'])
# app.config.from_object('as_config.DevelopmentConfig')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from models import AorticStenosis
login_key = app.config['LOGIN_KEY']
api_key = app.config['API_KEY']
model = app.config['MODEL']
api = BigML(login_key, api_key)
deepnet = Deepnet(model, api=api)
scaler = pkl.load(open("scaler.pkl", "rb"))
#app.route("/", methods=["GET", "POST"])
def home():
prediction = None
if request.method == "POST":
form_data = [
float(request.form.get("e_prime")),
float(request.form.get("LVMi")),
float(request.form.get("A")),
float(request.form.get("LAVi")),
float(request.form.get("E_e_prime")),
float(request.form.get("EF")),
float(request.form.get("E")),
float(request.form.get("E_A")),
float(request.form.get("TRV"))
]
form_data = scaler.transform([form_data])[0]
print(form_data)
prediction = str(deepnet.predict({
"e_prime": form_data[0],
"LVMi": form_data[1],
"A": form_data[2],
"LAVi": form_data[3],
"E_e_prime": form_data[4],
"EF": form_data[5],
"E": form_data[6],
"E_A": form_data[7],
"TRV": form_data[8]
}, full=True))
prediction = ast.literal_eval(prediction)
print(prediction)
## get ip address from the user
ip_address = request.environ['REMOTE_ADDR']
print("ip_address: ", ip_address)
try:
aorticStenosis = AorticStenosis(
ip_address = ip_address,
e_prime = form_data[0],
LVMi = form_data[1],
A = form_data[2],
LAVi = form_data[3],
E_e_prime = form_data[4],
EF = form_data[5],
E = form_data[6],
E_A = form_data[7],
TRV = form_data[8]
)
db.session.add(aorticStenosis)
db.session.commit()
except Exception as e:
print(str(e))
if prediction["prediction"] == "1":
prediction["prediction"] = "Low Risk"
prediction["probability"] = round(
1 - prediction["probability"], 6)
elif prediction["prediction"] == "2":
prediction["prediction"] = "High Risk"
else:
prediction["prediction"] = "No prediction was made!"
return render_template("home.html",
prediction=prediction["prediction"],
probability=prediction["probability"])
else:
return render_template("home.html")
if __name__ == "__main__":
app.run(host="0.0.0.0", port="8000")
I made a new file database.py and defined db there.
database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def init_app(app):
db.init_app(app)
app.py
import database
...
database.init_app(app)
models.py
from database import db
...

Flask BCrypt check_password_hash return False after saving via MongoEngine

I run into a weird situation, which is similar to this . This is my model:
class User(db.Document):
email = db.EmailField(required=True, unique=True)
username = db.StringField(max_length=50, required=True, unique=True )
password = db.StringField(required=True)
first_name = db.StringField(max_length=100, required=False)
last_name = db.StringField(max_length=100, required=False)
role = db.IntField(required = True, choices = role_choices, default = 5)
status = db.IntField(required = True, choices = status_choices, default = 1)
last_login = db.DateTimeField(required=False)
#property
def is_authenticated(self):
return True
#property
def is_active(self):
return True
#property
def is_anonymous(self):
return False
def __unicode__(self):
return self.username
def set_password(self, password):
self.password = bcrypt.generate_password_hash(password)
def __init__(self, *args, **kwargs):
username = kwargs.pop('username', None)
password = kwargs.pop('password', None)
email = kwargs.pop('email', None)
super(User, self).__init__(*args, **kwargs)
self.username = username
self.set_password(password)
self.email = email
meta = {
'allow_inheritance': False,
'indexes': ['-username'],
'ordering': ['-username']
}
def check_password(self, password):
return bcrypt.check_password_hash(self.password, password)
When I first create an instance of this User class, everything works as expected:
an = User(username="annguyen", first_name="An", last_name="Nguyen", password="janet78", email="an#gmail.com")
>>> an.password
'$2b$12$Ho9Q0/n4FPERytHKxA3szu8gzRZE4J9FxuZots8FFxJUKP6ULmqpe'
>>> an.save()
<User: annguyen>
>>> len(an.password)
60
>>> an.check_password('janet78')
True
However, when I retrieve this user from the database, the check_password method always return False.
>>> an_new = User.objects.get(username='annguyen')
>>> an_new.password
'$2b$12$j9VfNiySMKN19cYIEjuAseiamREUmGbB2ZFM4faoLJySB6uZfaCj2'
>>> len(an.password)
60
>>> len(an_new.password)
60
>>> an_new.check_password('janet78')
False
It is very clear that the password retrieved from the database is very different from what it was before being saved to the database, and therefore it always returns False. I spent a whole day trying to figure out what's wrong but couldn't come up with any clue. Can someone help point out how I can fix it.
I am developing on Windows 10 with Python 2.7, Flask 0.10.1, MongoDB 3.2, flask-mongoengine==0.7.5, mongoengine==0.10.6
Thanks a lot.

Facebook and linkedin not filling email field properly

Google and github logins are working properly but for some reason I cant get the facebook and linkedin accounts to properly fill the email fields.
Here are the involved files
__init__.py
db = SQLAlchemy(app)
login_manager=LoginManager()
login_manager.init_app(app)
# Import blueprints from app (example: from app.posts import posts)
from app.users import users
# Register all blueprints to the main app (example: app.register_blueprint(posts))
app.register_blueprint(users)
app.register_blueprint(social_auth)
#3rd part db interaction
init_social(app, db)
# Import main views from app
from app import views
#Set login bootback
login_manager.login_view ='/login'
app.context_processor(backends)
Settings.py configuration, keys have been removed from post
#Flask
SECRET_KEY = ''
SESSION_COOKIE_NAME = ''
### Python Social Auth ###
DEBUG_TB_INTERCEPT_REDIRECTS = False
SESSION_PROTECTION = 'strong'
#Redirects and Paths
SOCIAL_AUTH_LOGIN_URL = '/login'
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_BACKEND_ERROR_URL = '/login'
SOCIAL_AUTH_USER_MODEL = 'app.users.models.User'
SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
#Facebook
SOCIAL_AUTH_FACEBOOK_KEY=''
SOCIAL_AUTH_FACEBOOK_SECRET=''
#Google
SOCIAL_AUTH_GOOGLE_KEY=''
SOCIAL_AUTH_GOOGLE_SECRET=''
#LinkedIn
SOCIAL_AUTH_LINKEDIN_KEY=''
SOCIAL_AUTH_LINKEDIN_SECRET=''
#Github
SOCIAL_AUTH_GITHUB_KEY=''
SOCIAL_AUTH_GITHUB_SECRET=''
SOCIAL_AUTH_AUTHENTICATION_BACKENDS = (
'social.backends.google.GoogleOpenId',
'social.backends.google.GoogleOAuth2',
'social.backends.google.GoogleOAuth',
'social.backends.facebook.FacebookOAuth2',
'social.backends.linkedin.LinkedinOAuth',
'social.backends.github.GithubOAuth2',
)
Here is the model itself, follows pretty closely the example provided by omab
models.py
from __future__ import absolute_import, print_function
from time import time
import functools
import uuid
import pbkdf2
from marshmallow import Serializer, fields
from app import db
ROLE_USER=0
ROLE_ADMIN=1
ROLE_GOD=2
default_img = '/assets/images/avatars/default.jpg'
class User(db.Model):
#meat n' potatoes
id = db.Column(db.Integer, primary_key=True)
img=db.Column(db.String(255), default=default_img)
username = db.Column(db.String(255))
email = db.Column(db.String(200), unique=True)
first_name = db.Column(db.String(30))
last_name = db.Column(db.String(40))
created_at = db.Column(db.BigInteger, default=time())
#controls
role = db.Column(db.SmallInteger, default=ROLE_USER)
is_active = db.Column(db.Boolean, default=True)
is_authenticated= db.Column(db.Boolean, default=True)
#password
salt = db.Column(db.String(50))
pass_hash = db.Column(db.String(255))
def __unicode__(self):
return self.email
def __repr__(self):
return '<User %r>' % self.email
def is_authenticated(self):
return self.is_authenticated
def is_anonymous(self):
return False
def is_active(self):
return self.is_active
def get_id(self):
return unicode(self.id)
def _check_password(self, password):
hash_check = pbkdf2.crypt(password, self.salt, 1000)
if hash_check ==self.pass_hash:
valid=True
else:
valid=False
return valid
def validate_user(self,password):
p=self.check_password(password=password)
if p:
return True;
else:
return False;
meta = {
'allow_inheritance': True,
'indexes': ['-created_at'],
'ordering': ['-created_at']
}
class UserSerializer(Serializer):
id=fields.Integer()
img=fields.String()
email=fields.String()
first_name=fields.String()
last_name=fields.String()
Found this in the docs silly of me not to realize that they would have different request parameters:
http://psa.matiasaguirre.net/docs/backends/index.html
UPDATE:
See this answer from Babken Vardanyan
https://stackoverflow.com/a/46807907/2529583