How to define a marshamllow List field using marshmallow_sqlalchemy - flask

I'm trying to create a Schema using marshmallow_sqlalchemy. I want to create a list out of two entries of the Database, x_coordinate and y_coordinate, however, I'm not sure how to do that.
Here's the Schema
from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
class LocationSQLAlchemySchema(SQLAlchemySchema):
class Meta:
model = Location
load_instance = True
location_id = auto_field('id')
name = auto_field('name')
user_uid = auto_field('customer_id')
maps_url = auto_field('maps_url')
coordinates = fields.List(Meta.model.x_coordinate,Meta.model.y_coordinate) #This is what I don't know how to define.
Here's the Model I'm using for this Schema:
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.mysql import INTEGER
db = SQLAlchemy()
class Location(db.Model):
__tablename__ = 'cleaning_locations'
id = db.Column(db.String(128), primary_key=True, unique = True)
name = db.Column(db.String(45), nullable = False)
customer_id = db.Column(db.String(45),nullable = False)
maps_url = db.Column(db.String(2048),nullable = False)
x_coordinate = db.Column(db.Numeric(precision = 8, scale=5), nullable = False)
y_coordinate = db.Column(db.Numeric(precision = 8, scale=5), nullable = False)
address = db.Column(db.String(255))
country = db.Column(db.String(45))
state = db.Column(db.String(45))
size = db.Column(INTEGER(unsigned=True), nullable = False )
rooms = db.Column(INTEGER(unsigned=True), nullable = False )
bathrooms = db.Column(INTEGER(unsigned=True), nullable = False )
kitchens = db.Column(INTEGER(unsigned=True), nullable = False )
How can I make the Schema to represent the coordinates as a list containing the x_coordinate and the y_coordinate?
(newbie extra question). Is it a bad practice to use diferent variable names in the db model and in the Schema?

Please try this (untested):
from marshmallow_sqlalchemy import field_for
[...]
coordinates = fields.Tuple(
(field_for(Location, "x_coordinate"), field_for(Location, "y_coordinate"))
)
Not sure it is the best idea here because then you can't just cram the data loaded from the schema into the object init. But nothing prevents you from having an API (schemas) that differs from the DB representation.

Related

class.query.all() returning only last added value

I am trying to create an api that gets it's response from a flask-sqlalchemy database. But anytime I make a get request on postman it returns the last added data to the database only and I am trying to get all the data.
Below is my database model
class Data(db.Model):
uuid = db.Column(db.String(60), name = "uuid", nullable = False, primary_key = True)
timestamp = db.Column(db.DateTime, nullable = False, default = datetime.utcnow, primary_key=True)
decibel = db.Column(db.Integer, nullable = False)
then my get all request
class Sensor(Resource):
def get(self):
datas = Data.query.all()
all = {}
for data in datas:
all = {"uuid":str(data.uuid), "timestamp":str(data.timestamp), "decibel":data.decibel}
return all
Then my post request although this works just fine
class SensorData(Resource):
#marshal_with(resource_fields)
def post(self):
args = sensor_post.parse_args()
sensor_new =Data(uuid = args['uuid'], decibel = args["decibel"])
if args['uuid'] != generate_UUID():
abort(405)
db.session.add(sensor_new)
db.session.commit()
return sensor_new, 201
api.add_resource(SensorData, "/sensor")
api.add_resource(Sensor, "/sensor/all")
Please I would appreciate any form of help on this

query that must exclude me from the whole list

hi i have a problem with this filter. group_to_add takes some values ​​which should filter out the problem that I don't want those values ​​but I want the others without those.
I would like to find a way to take those values ​​and subtract them from others.
group_to_add = DatiGruppi.objects.filter(gruppi_scheda = scheda.id)
GruppiForm.base_fields['dati_gruppo'] = forms.ModelChoiceField(queryset = group_to_add)
I asked a similar question I leave the link
select filtering and removal if they are already present in the db
models
class Schede(models.Model):
nome_scheda = models.CharField(max_length=100)
utente = models.ForeignKey(User, on_delete = models.CASCADE,related_name = 'utente')
class DatiGruppi(models.Model):
dati_gruppo = models.ForeignKey(Gruppi,on_delete = models.CASCADE, related_name = 'dati_gruppo')
gruppi_scheda = models.ForeignKey(Schede,on_delete = models.CASCADE, related_name = 'gruppi_scheda')
class Gruppi(models.Model):
nome_gruppo = models.CharField(max_length=100)
I have this tab where inside there are saved data groups that contain groups that are inside a select the correct exclusion would be
group_to_add = Gruppi.objects.exclude(dati_gruppo = 147)
but instead of 147 I have to put the id of the data group of that board
view
def creazione(request, nome):
scheda = get_object_or_404(Schede, nome_scheda = nome)
eserciziFormSet = formset_factory(EserciziForm, extra = 0)
if request.method == "POST":
gruppo_form = GruppiForm(request.POST, prefix = 'gruppo')
if gruppo_form.is_valid():
gruppo = gruppo_form.save(commit = False)
gruppo.gruppi_scheda = scheda
gruppoName = gruppo_form.cleaned_data['dati_gruppo']
gruppo.save()
esercizi_formset = eserciziFormSet(request.POST, prefix='esercizi')
for esercizi in esercizi_formset:
esercizi_instance = esercizi.save(commit = False)
esercizi_instance.gruppo_single = get_object_or_404(DatiGruppi, gruppi_scheda = scheda.id, dati_gruppo = gruppoName)
esercizi_instance.save()
return HttpResponseRedirect(request.path_info)
else:
group_to_add = Gruppi.objects.exclude(dati_gruppo = 147)
GruppiForm.base_fields['dati_gruppo'] = forms.ModelChoiceField(queryset = group_to_add)
gruppo_form = GruppiForm(prefix = 'gruppo')
esercizi_formset = eserciziFormSet(prefix='esercizi')
context = {'scheda' : scheda, 'gruppo_form' : gruppo_form, 'esercizi_formset': esercizi_formset}
return render(request, 'crea/passo2.html', context)
If I understand it correctly, you should use .exclude(…) [Django-doc] not .filter(…) [Django-doc]:
group_to_add = Gruppi.objects.exclude(
dati_gruppo__gruppi_scheda=scheda
)
GruppiForm.base_fields['dati_gruppo'] = forms.ModelChoiceField(queryset=group_to_add)

Invalid ObjectId when saving to a ReferenceField in Mongo

so I have this model set up with django and mongoengine.
class Product(Document):
product_id = IntField()
title = StringField(max_length=255)
sources = ListField(ReferenceField(Source, dbref = True))
class Source(Document):
source_id = IntField()
source_type = StringField(choices=settings.PARENT_TYPE_CHOICES, max_length=50)
name = StringField(max_length=255)
url = URLField(max_length=2000)
meta = {"allow_inheritance": True}
And in my scrapy pipeline I save the following data:
class SaveItemPipeline(object):
def process_item(self, item, spider):
product = item["product"]
product["sources"] = self.create_sources(product)
saved_product,created = Product.objects.get_or_create(**product)
return item
def create_sources(self,product):
temp_sources = []
for source in product["sources"]:
print source
if source["source_type"] == "user":
temp_source,created = UserSource.objects.get_or_create(**source)
elif source["source_type"] == "store":
temp_source,created = StoreSource.objects.get_or_create(**source)
elif source["source_type"] == "collection":
temp_source,created = CollectionSource.objects.get_or_create(**source)
temp_sources.append(temp_source.id)
return temp_sources
Howerver, when I run the scraper, on save it gives me this error:
raise ValidationError(message, errors=errors, field_name=field_name)
mongoengine.errors.ValidationError:
[ObjectId('55787a07516ddcf4d93cd4c6'),
ObjectId('55787b07516ddcf5aff06fa9'),
ObjectId('55787b07516ddcf5aff06faa')] is not a valid ObjectId
By the way the UserSource and StoreSource...all inherit from Source so they are just subclasses.However, am I doing anything wrong here, I don't understand why it is giving me that error when product gets created.
Thanks!
You can use this
class Source(Document):
source_id = IntField()
class Product(Document):
sources = ListField(ReferenceField(Source, dbref = True))
src, created = Source.objects.create(source_id=1)
pd, _ = Product.objects.create(sources=[src])
It works for me. I am using mongoengine 0.8.7, pymongo 2.8

Django foreign key is not set and hence unable to save form

I have a simple foreign key relationship between two tables. I am able to save the parent, but am unable to save the child which has a foreign key to the parent. This is what my models look like:
class Product(models.Model):
month_choices = tuple((m,m) for m in calendar.month_abbr[1:])
year_choices = tuple((str(n), str(n)) for n in range(2004, datetime.now().year +2 ))
id = models.AutoField(primary_key = True)
title = models.CharField(max_length = 1024)
product_type = models.ForeignKey(ProductType)
month = models.CharField(max_length =3, choices=month_choices)
year = models.CharField(choices=year_choices, max_length = 4)
project = models.CharField(max_length = 15, null = True, blank = True)
url = models.URLField(null = True, blank = True)
export_to_xsede = models.BooleanField()
#def __str__(self):
# return str(self.id)
class Meta:
db_table = "product"
class ProductResource(models.Model):
CHOICES = (('A','A'),('B','B'),('C','C'),('D','D'),('E','E'))
id = models.AutoField(primary_key = True)
product = models.ForeignKey(Product)
resource = models.CharField(choices=CHOICES, max_length = 15)
And my views:
class PublicationForm(forms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'size':'70'}),required=False)
url = forms.CharField(widget=forms.TextInput(attrs={'size':'70'}),required=False)
class Meta:
model = Product
class ResourceForm(forms.ModelForm):
resource = forms.MultipleChoiceField(choices=ProductResource.CHOICES, widget = forms.CheckboxSelectMultiple)
class Meta:
model = ProductResource
I save the parent:
saved_publication = publications_form.save()
but am unable to save the resource form:
resource_form = ResourceForm(request.POST, instance = saved_publication)
resource_form.product = saved_publication
resource_form.save()
When I print resource_form.errors, I get:
<ul class="errorlist"><li>product<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
I have no idea why the foreign key is not getting set in this case.
I'm assuming you do not want to display the product field on the form, so you should exclude it from the form so the validation will pass:
class ResourceForm(forms.ModelForm):
resource = forms.MultipleChoiceField(choices=ProductResource.CHOICES, widget = forms.CheckboxSelectMultiple)
class Meta:
model = ProductResource
exclude = ['product']
Then in the view, just set the product manually after calling is_valid(). Just be sure to pass commit=False on the form.save() so that it will not actually save to the database until after you set the product. For example
...
saved_publication = publications_form.save()
resource_form = ResourceForm(request.POST)
if resource_form.is_valid():
resource = resource_form.save(commit=False)
resource.product = saved_publication
resource.save()

Relation between models with composite keys

I have two models with composite keys:
class ContestUser(models.Model):
user_id = models.IntegerField(primary_key = True)
contest_id = models.IntegerField(primary_key = True)
username = models.CharField(max_length = 1536, blank = True)
.
.
.
class ContestRegistration(models.Model):
user_id = models.IntegerField(primary_key = True)
contest_id = models.IntegerField(primary_key = True)
status = models.IntegerField(choices = EJUDGE_CONTEST_STATUSES)
.
.
.
First question is How can I relate them, and query like in join.
Select * from ContestRegistration r join ContestUser u on r.user_id = u.user_id and r.contest_id = u.contest_id where r.contest_id = 3;
Second is How to save an object like this?
cuser = ContestUser.objects.get(user_id = 1, contest_id = 1)
cuser.username = 'username'
cuser.save()
This results in IntegrityError: (1062, "Duplicate entry '1-1' for key 'PRIMARY'")
Executed SQL is:
SELECT * FROM `users` WHERE (`users`.`contest_id` = 1 AND `users`.`user_id` = 1 );
SELECT (1) AS `a` FROM `users` WHERE `users`.`user_id` = 1 LIMIT 1;
UPDATE `users` SET ... WHERE `users`.`user_id` = 1 ;
Django models don't support multiple primary keys: https://docs.djangoproject.com/en/1.3/faq/models/#do-django-models-support-multiple-column-primary-keys
However, as the documentation describes, you can use other properties on ForeignKey fields, like unique_together to do the same thing. Hope that helps you out.