How to add a custom field in Flask-Marshmallow which is not a part of my SQLAlchemy Model - flask-sqlalchemy

Suppose I have my Model class as below.
class BankAccount(db.Model):
a = db.Column(db.Integer, primary_key=True)
b = db.Column(db.String(80))
And my Schema looks like the below.
class CreateAccountSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = BankAccount
load_instance = True
ordered = True
But here I want to define a field c which doesnt exists in my Model class as it should only be used for dump(ing) values and not storing in the database.
Something like...
class CreateAccountSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = BankAccount
dump_only = ('c',)
load_instance = True
ordered = True
c = #somedefination

You could do something like this:
class CreateAccountSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = BankAccount
load_instance = True
ordered = True
c = fields.Method("get_data")
def get_data(self, obj):
if hasattr(obj, "data"):
return obj.data
return None
That would dump the additional field.
You could use it like this:
bank_account = db.session.query(BankAccount).first()
bank_account.data = "whatever"
schema = CreateAccountSchema()
schema.dump(bank_account)
More infos here.

Related

Cannot resolve keyword into field error while using drf model serializer and search_fields within field set?

SerializerClass:
class VacancySerializer(serializers.ModelSerializer):
organization_small_name = serializers.CharField(source='organization.short_name', read_only=True)
class Meta:
model = Vacancy
fields = ['organization', 'description', 'specs', 'type', 'publication_date',
'is_published', 'withdrawal_data', 'organization_small_name', ]
read_only_fields = ['publication_date', 'is_published', 'withdrawal_data',]
ViewSet:
class VacancyViewSet(viewsets.ModelViewSet):
queryset = Vacancy.objects.all()
serializer_class = VacancySerializer
filter_backends = [filters.SearchFilter]
search_fields = ['organization_small_name']
...
Model:
class Vacancy(models.Model):
organization = models.OneToOneField(DictOrganization, on_delete=models.CASCADE, related_name='vacancies')
description = models.TextField('Описание')
specs = models.ManyToManyField(DictSpec, blank=True)
type = models.CharField('Тип', max_length=20, choices=VacancyType.choices(), default=VacancyType.PRACTICE.value)
publication_date = models.DateField('Дата публикации', null=True, blank=True)
is_published = models.BooleanField('Опубликовано', default=False)
withdrawal_data = models.DateField('Дата снятия с публикации', null=True, blank=True)
My goal is to make API search by 'organization_small_name' field
that is in VacancySerializer.
Server runs successfully, but as soon as i add ?search parameter, i get next error:
Why it doesn't recognize 'organization_small_name' field, even thought it is decribed in serializer, and how can i fix it?

Odoo, can't have two different siblings objects in the same view

I have a class named detail_base, and two other classes name flight_detail and tour_detail, the last two classes inherits from the first one, like this:
class DetailBase(models.Model):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherits = 'detail_base'
passport = fields.Char('Passport')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherits = 'detail_base'
age = fields.Integer('Tourist Age')
The problem is when I call the flight_detail and tour_detail in the same view, the browser can't handle the common attributes of both classes, If I assign 5 to tour_detail.fee, that number will be stored into flight_detail.fee.
It seems the problem is related to the attributes with the same name of different objects being siblings.
I will appreciate any help.
You should either use _inherit
class DetailBase(models.AbstractModel):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherit = 'detail_base'
passport = fields.Char('Passport')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherit = 'detail_base'
age = fields.Integer('Tourist Age')
which should either create 3 database tables (detail_base as Model) or 2 database tables (AbstractModel).
Or you use _inherits like:
class DetailBase(models.Model):
_name = 'detail_base'
fee = fields.Monetary('Fee')
passenger = fields.Char('Passenger')
class FlightDetail(models.Model):
_name = 'flight_detail'
_inherits = {'detail_base': 'base_id'}
passport = fields.Char('Passport')
base_id = fields.Many2one('detail_base', required=True, ondelete='cascade')
class TourDetail(models.Model):
_name = 'tour_detail'
_inherit = {'detail_base': 'base_id'}
age = fields.Integer('Tourist Age')
base_id = fields.Many2one('detail_base', required=True, ondelete='cascade')
That will create 3 tables, and fee and passenger will be stored in detail_base table. Odoo will get it from there, because it is a sort of delegation inheritence.
use inherit:
1- inherit without _name :
inherit = 'model.name'
new_field = fields...
this add this field to the model.name
2- inherit with _name:
inherit = 'model.name'
_name = 'new.model'
here will create a new tabel in database with the same structure of model.name.
inherits: The delegation inheritance.
best example is res.users and res.partners user is a partener so when we create a res.users record we must create a res.partener that hold commun field like name, email, address ... and information related to users like passowrd and login are stored in res.users model and with type of inheritence you can access field of res.partener directly without having to create a related field. you can do user_record.name or .email or .address this will not be a problem.
i like to think of it as one2one relation.
_inherits = {model.name : many2one_field_id }
_name = 'new.model'
# m2o field should be required and ondelete = cascade
many2one_field_id = fields.Many2one('model.name', string='Label', required=True, ondelete="cascade")
so when you create a record of new.model all field that are in model.name will be stored in model.name.

Django rest framework reverse relation serializers exclude fields

I have two models Question and Options
class Question(models.Model):
question_identifier = models.CharField(max_length=255)
question_text = models.TextField(blank=False)
question_category = models.ManyToManyField('Category')
question_tags = models.CharField(max_length=255, blank=True)
class Options(models.Model):
question = models.OneToOneField('Question', related_name='options', blank=False, null=False)
option1 = models.CharField(max_length=255,blank=False,null=True)
option2 = models.CharField(max_length=255,blank=False,null=True)
option3 = models.CharField(max_length=255,blank=True,null=True)
option4 = models.CharField(max_length=255,blank=True,null=True)
I have written a serializer for Question model which serializes options as well (reverse relation). I want to omit the question field from the Options? Is there a way to achieve this?
My Question Serializer:-
class QuestionSerializer(serializers.ModelSerializer):
"""
Serializer for Question object from qna.models
"""
question_category = CategorySerializer(many=True,write_only=True)
class Meta:
model = Question
fields = ('id', 'options', 'question_identifier','question_text','question_tags','question_category')
depth = 1
You can achieve that by creating a separate serializer for an Options model.And use it instead of default field, without depth value.
class OptionsSerializer(serializers.ModelSerializer):
class Meta:
model = Options
fields = ('option1', 'option2', 'option3')
class QuestionSerializer(serializers.ModelSerializer):
question_category = CategorySerializer(many=True,write_only=True)
options = OptionsSerializer()
class Meta:
model = Question
fields = ('id', 'options', 'question_identifier','question_text','question_tags','question_category')

Filter query with variable list in django

I have a three table model like that :
I want to filter results of a query with a variable list of items for exemple :
listTags = ["landscape","green"]
results = ListTag.objects.filter(tag__name__in=listTags).select_related()
But the result of that query is all the ListTag objects with landscape OR green but what i want it's a list of ListTag objects with landscape AND green
I saw a lot a of answers about that problem but a lot of them use a static list of tags, what i want it's to filter with a variable listtags list
Edit : the model
class Picture(models.Model):
title = models.CharField(max_length=50,null=True, blank=False, verbose_name=('name'))
def __str__(self):
return self.titre
class Tag(models.Model):
name = models.CharField(max_length=50,null=True, blank=False, verbose_name=('name'))
def __str__(self):
return self.name
class ListTags(models.Model):
picture = models.ForeignKey(Picture, blank=False, on_delete=models.CASCADE, related_name='picture')
tag = models.ForeignKey(Tag, blank=False, on_delete=models.CASCADE, related_name='tag')
You can try to use Django Q object.
In your case this could be:
from django.db.models import Q
...
listTags = ["landscape","green"]
query = Q()
for tag in listTags:
query &= Q(tag__name = tag)
results = ListTag.objects.filter(query).select_related()
addition:
if you want just pictures with tags, then you could use many-to-many relationships. But if you want use tags for different types of models, then u need to use generic relations.
In first case models structure could be:
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=50, null=True, blank=False, verbose_name=('name'))
def __str__(self):
return self.name
class Picture(models.Model):
title = models.CharField(max_length=50, null=True, blank=False, verbose_name=('name'))
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.title
With m2m relation Q object will not work, so to get all pictures with landscape and green tags you can use filter chaining:
listTags = ["landscape", "green"]
results = models.Picture.objects.all()
for tag in listTags:
results = results.filter(tags__name = tag)
I believe the code below would make this an AND query rather than an OR query:
listTags = ["landscape","green"]
filters = {}
for value in listTags:
filters['tag__name__in'] = value
results = ListTag.objects.filter(**filters)

Issue with complex Django join query

I can't find a valid way with Django OMR in order to get : ( a raw query is also fine )
the Sites.sitename which made the Analysis where (Analysi_Items.name='somename' and Analysis_Items.value='somevalue') and (Analysi_items_name='somename' and Analysis_Items.value='somevalue') and (Analysis_items.name='somename' and Analysis_Items.value='somevalue').
class Sites(models.Model):
region = models.CharField(max_length=1000)
province = models.CharField(max_length=1000)
sitename = models.CharField(max_length=1000, primary_key=True)
class Meta:
verbose_name_plural = "Sites"
def __unicode__(self):
return self.sitename
class Analysis_Items(models.Model):
code = models.ForeignKey('Analysis')
name = models.CharField(max_lenght=100)
value = models.CharField(max_length=20)
class Meta:
verbose_name_plural = "Analysis Type"
class Analysis(models.Model):
date = models.DateField()
site = models.ForeignKey('Sites')
def __unicode__(self):
return str(self.date)
class Meta:
verbose_name_plural = "Analysis"
Hope this is clear enough. thank you in advance!
Site.objects.filter(analysis__analysis_items__name='some_name', analysis__analysis_items__value='some_value')
You can keep adding additional parameters in the same keep AND'ing them all together.