Not able to get joins in flask Marshmellow and sql alchemy - flask

I want to get the producttype with admin info who added the producttype I am using sqlalchemy with postgresql and marshmallow
This is my Model related info related to Admin
class Admin(db.Model):
id = db.Column(db.Integer, primary_key=True)
full_name = db.Column(db.String())
email = db.Column(db.String(), unique=True)
mobile = db.Column(db.String(), unique=True)
password = db.Column(db.String())
product_types: db.relationship("ProductType", backref="admin", lazy=True)
created_at = db.Column(DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(DateTime(timezone=True), onupdate=func.now())
def __repr__(self):
return "<Admin %r>" % self.full_name
class AdminSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Admin
admin_schema = AdminSchema()
admins_schema = AdminSchema(many=True)
This is my Model related info related to Product_Type
class ProductType(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
descripton = db.Column(db.String())
added_by_id = db.Column(db.Integer, db.ForeignKey("added_by.id"))
added_by: db.relationship("Admin", backref=db.backref("admin", lazy="dynamic"))
created_at = db.Column(DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(DateTime(timezone=True), onupdate=func.now())
def __repr__(self):
return "<ProductType %r>" % self.name
class ProductTypeSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = ProductType
added_by = ma.Nested(AdminSchema)
product_type_schema = ProductTypeSchema()
product_types_schema = ProductTypeSchema(many=True)
If anyone can suggest something please do
I want to get the producttype with admin info who added the producttype I am using sqlalchemy with postgresql and marshmallow.
The output I am expecting
product_type:{
"created_at": "2023-01-21T07:55:14.773346+05:30",
"descripton": "Product Type",
"id": 6,
"name": "dgd",
"updated_at": null,
"admin":{
"full_name":""
"email":""
"mobile":""
}
}

Unfortunately, your code contains syntax errors as well as an inaccurate definition of the database relationships. For this reason it is difficult to interpret exactly what your database looks like or which renaming the schemas must contain.
As a note on defining relationships:
The referencing via ForeignKey expects the names of the table and the primary key column separated by a period.
The backref parameter defines the name of the attribute under which the back reference is accessible.
The following example shows a possible implementation to achieve the output you are aiming for.
class Admin(db.Model):
id = db.Column(db.Integer, primary_key=True)
full_name = db.Column(db.String())
email = db.Column(db.String(), unique=True)
mobile = db.Column(db.String(), unique=True)
password = db.Column(db.String())
created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
class AdminSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = Admin
exclude = ('password',)
class ProductType(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
description = db.Column(db.String())
admin_id = db.Column(db.Integer, db.ForeignKey("admin.id"))
admin = db.relationship("Admin", backref=db.backref("product_types", lazy="dynamic"))
created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
class ProductTypeSchema(ma.SQLAlchemyAutoSchema):
class Meta:
model = ProductType
admin = ma.Nested(AdminSchema(only=('full_name','mobile', 'email')))

Related

How to display many fields' values with ForeignKey relationship?

Looking for solution of this problem I encountered some similar threads, but referring to older versions of Django/DRF and thus not working in my case.
There are these two models:
class CsdModel(models.Model):
model_id = models.CharField("Item ID", max_length=8, primary_key=True)
name = models.CharField("Item Name", max_length=40)
active = models.BooleanField(default=True)
def __str__(self):
return self.model_id
class CsdListing(models.Model):
model_id = models.ForeignKey(CsdModel, on_delete=models.CASCADE, default=0, related_name='m_id')
name = models.ForeignKey(CsdModel, on_delete=models.CASCADE, default=0, related_name='m_name')
(...)
EDIT: Serializers are defined this way:
class CsdModelSerializer(serializers.ModelSerializer):
model_id = serializers.RegexField(regex='^\w{2}\d{3}$', allow_blank=False)
name = serializers.CharField(min_length=6, max_length=50, allow_blank=False)
class Meta:
model = CsdModel
fields = '__all__'
class CsdListingSerializer(serializers.ModelSerializer):
session_id = serializers.RegexField(regex='^s\d{2}$', allow_blank=False)
def validate_session_id(self, value):
(...)
class Meta:
model = CsdListing
fields = '__all__'
What I'd like to see, is model_id and name from CsdModel displayed inside a form created based on CsdListing model. But instead, the ID is duplicated:
How should I rebuild the model(s) to have both ID and name displayed in the form?
You should have only one foreign key. But the listing serializer should then reference the model as a nested serializer.
class CsdListing(models.Model):
model = models.ForeignKey(CsdModel, on_delete=models.CASCADE, default=0, related_name='listing')
class CsdListingSerializer(serializers.ModelSerializer):
model = CsdModelSerializer()
session_id = serializers.RegexField(regex='^s\d{2}$', allow_blank=False)

Multiple default values specified for column "id" of table in Django 2.1.1

So I keep getting this error saying that there's multiple specified ID values for the device table, but I don't have a clue where I've specified any kind of default ID. I've tried setting a field as primary_key=True but that didn't solve the problem either.
EDIT: Traceback
class Campus(models.Model):
name = models.CharField(max_length=20)
address = models.CharField(max_length=40)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Campuses"
class Teacher(models.Model):
name = models.CharField(max_length=20)
phone = models.CharField(max_length=11)
department = models.CharField(max_length=20)
campus = models.OneToOneField(Campus, on_delete=models.CASCADE, default="Not Assigned")
#devices = self.Device.objects.all()
def __str__(self):
return self.name
class Device(models.Model):
inUse = 'IU'
inStock = 'IS'
inMaintenance = 'IM'
damaged = 'DM'
statusChoices = (
(inUse, 'In Use'),
(inStock, 'In Stock'),
(inMaintenance, 'In Maintenance'),
(damaged, 'Damaged'),
)
name = models.CharField(max_length=20)
brand = models.CharField(max_length=20)
status = models.CharField(max_length=2, choices=statusChoices, default=inStock)
#user = models.ForeignKey(Teacher, on_delete=models.CASCADE, default=0)
def __str__(self):
return self.name
After navigating to my PostgreSQL instance I deleted all Django-related data and remade migrations and things are in working order again.
For future users: I recommend deleting your past migrations table in your database.

How to serialize nested model in Django-Rest

I have been trying to use with the a legacy database. I have created models file using inscpectdb but now I am not able to perform joins on the table.
I have two tables job_info and username_userid.
Here is my models.class file:
class UseridUsername(models.Model):
userid = models.IntegerField(blank=True, null=True)
username = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'userid_username'
class LinuxJobTable(models.Model):
job_db_inx = models.AutoField(primary_key=True)
mod_time = models.IntegerField()
account = models.TextField(blank=True, null=True)
exit_code = models.IntegerField()
job_name = models.TextField()
id_job = models.IntegerField()
id_user = models.OneToOneField(UseridUsername , on_delete=models.CASCADE,db_column="id_user")
class Meta:
managed = False
db_table = 'linux_job_table'
Now how can I get all the values from LinuxJobTable and username from UseridUsername for the corresponding user.
Heren is my serializable class :
class UseridUsernameSerializer(serializers.ModelSerializer):
class Meta:
model = UseridUsername
fields = ('userid','username')
class UserSerializer(serializers.ModelSerializer):
class Meta:
username = UseridUsernameSerializer(many=False)
model = LinuxJobTable
fields = ('account','mod_time','username')
When I try to access it, it gives ' Field name username is not valid for model LinuxJobTable.' error.
The error is raising because UserSerializer search for a relates fields named username and it doesn't find a one. In your case the ralated field is named as id_user, So you have to mention it via source parameter.
So, Try this
class UserSerializer(serializers.ModelSerializer):
username = UseridUsernameSerializer(many=False, source='id_user')
class Meta:
model = LinuxJobTable
fields = ('account', 'mod_time', 'username')

select related in Django

I am trying to accomplish something very similar to:
How to join 3 tables in query with Django
Essentially, I have 3 tables. In the Django REST we are showing table 3. As you see below (models.py), table 3 has company_name which is a foreign key of table 2 and table 2 is a foreign key of table 1. Both table 2 and 3 are linked by the table 1 ID. Table 1 contains the actual text, which we want to display in the API output, not the ID number.
Table 1: Manufacturer of Car -- Table 2: What the Car is -- Table 3: list of all cars
Models.py
Table 1:
class ManufacturerName(models.Model):
name_id = models.AutoField(primary_key=True)
company_name = models.CharField(unique=True, max_length=50)
class Meta:
managed = False
db_table = 'manufacturer_name'
Table 2:
class CarBuild(models.Model):
car_id = models.AutoField(primary_key=True)
car_icon = models.CharField(max_length=150, blank=True, null=True)
company_name = models.ForeignKey('ManufacturerName', models.DO_NOTHING, db_column='ManufacturerName')
class Meta:
managed = False
db_table = 'car_build'
Table 3:
class CarList(models.Model):
list_id = models.AutoField(primary_key=True)
company_name = models.ForeignKey('CarBuild', models.DO_NOTHING, db_column='CarBuild')
title = models.CharField(unique=True, max_length=100)
description = models.TextField()
class Meta:
managed = False
db_table = 'cars'
Within my views:
This is what I am trying, based on the foreign key relationships:
queryset = CarList.objects.all().select_related('company_name__company_name')
I get no errors when I save and run this, however, the ID is still being returned, and not the text associated with the foreign key relationships:
[
{
"list_id": 1,
"company_name": "http://127.0.0.1:8000/api/1/",
"title": "Really fast car you're driving, and this is dummy text",
Again, I would like to achieve getting the text associated with the company_name foreign key relationships from table 1 to show in the JSON.
serializer and viewset
class manufacturer_name(serializers.HyperlinkedModelSerializer):
class Meta:
model = manufacturer_name
fields = ('name_id', 'company_name')
class manufacturer_name(viewsets.ModelViewSet):
queryset = manufacturer_namee.objects.all()
serializer_class = manufacturer_name
class CarBuildViewSet(viewsets.ModelViewSet):
queryset = CarBuild.objects.all()
serializer_class = CarBuildSerialiser
class CarBuildSerialiser(serializers.HyperlinkedModelSerializer):
class Meta:
model = CarBuild
fields = ('car_id', 'car_icon', 'company_name')
class CarListSerialiser(serializers.HyperlinkedModelSerializer):
class Meta:
model = News
fields = ('list_id', 'company_name', 'title')
class CarListViewSet(viewsets.ModelViewSet):
serializer_class = CarList
def get_queryset(self):
queryset = News.objects.all().select_related('company_name__company_name')
return queryset
Based on detailed conversation to clear few details. Here is the answer.
You need to make small changes to your models as it was quite confusing to understand what you want to achieve.
Models:
class ManufacturerName(models.Model):
name_id = models.AutoField(primary_key=True)
company_name = models.CharField(unique=True, max_length=50)
class Meta:
managed = False
db_table = 'manufacturer_name'
class CarBuild(models.Model):
car_id = models.AutoField(primary_key=True)
car_icon = models.CharField(max_length=150, blank=True, null=True)
manufacturer = models.ForeignKey(ManufacturerName,on_delete=models.SET_NULL)
class Meta:
managed = False
db_table = 'car_build'
class CarList(models.Model):
list_id = models.AutoField(primary_key=True)
car = models.ForeignKey(CarBuild, on_delete=models.DO_NOTHING)
title = models.CharField(unique=True, max_length=100)
description = models.TextField()
class Meta:
managed = False
db_table = 'cars'
And then You need to adjust your serializers.
class CarListSerialiser(serializers.HyperlinkedModelSerializer):
company_name= serializers.SerializerMethodField(read_only=True)
class Meta:
model = CarList
fields = ('list_id', 'company_name', 'title')
def get_company_name(self, obj):
return obj.car.manufacturer.company_name
And you use it in your view:
class CarListViewSet(viewsets.ModelViewSet):
queryset = CarList.object.all()
serializer_class = CarListSerialiser

How to serialize a self recursive many-to-many model using a through table in django rest_framework?

i am developing a rest API using django rest framework and i am stuck at a serializer the idea is to serialize a self recursive many to many model using a through table my code is:
model.py:
class Patient(models.Model):
class Meta:
db_table = 'patients'
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
id_card = models.CharField(max_length=45)
dob = models.DateField()
gender = EnumChoiceField(enum_class=Gender)
patientscol = models.CharField(max_length=45)
fk_user = models.ForeignKey(Users, related_name='user_patient', on_delete=models.CASCADE)
relative = models.ManyToManyField("self", through='PatientHasRelative')
class PatientHasRelative(models.Model):
class Meta:
db_table = 'patients_has_relatives'
fk_patient = models.ForeignKey(Patient, related_name='patient_has', on_delete=models.CASCADE)
fk_relative_patient = models.ForeignKey(Patient, related_name='patient_relative', on_delete=models.CASCADE)
relationship = EnumChoiceField(enum_class=Relationship)
my serializer.py is:
class PatientSerializer(serializers.ModelSerializer):
class Meta:
model = Patient
fields = ('__all__')
id = serializers.UUIDField(read_only=True)
id_card = serializers.CharField(required=True, max_length=45)
dob = serializers.DateField(required=True)
gender = EnumChoiceField(enum_class=Gender)
fk_user = serializers.PrimaryKeyRelatedField(required=True, queryset=Users.objects.all())
relative = PatientSerializer(read_only=True, required=True)#problem is here i cant use PatientSerializer here
class PatientHasRelativeSerializer(serializers.ModelSerializer):
class Meta:
model = PatientHasRelative
fields = ('__all__')
fk_patient = serializers.PrimaryKeyRelatedField(required=True, queryset=Patient.objects.all())
fk_relative_patient = serializers.PrimaryKeyRelatedField(required=True, queryset=Patient.objects.all())
relationship = EnumChoiceField(enum_class=Relationship)
a little help would be appreciated
To accomplish this you need to define related_name in the source model on the source field ie add
class Patient(models.Model):
relatives = models.ManyToManyField(
"self", through='PatientHasRelative', related_name='patients')
with this related_name you can easily access -- add/delete/set relatives/patients on either side of the relationships in the serializers
You can either do this using intermediary model
relative = Patient(**key_value_fields)
patient = Patient(**key_value_field)
PatientHasRelative.objects.create(
relative=relative, patient=patient, through_defaults=(relationship ='value',))
or you can do this
relative.patients.add(patient, through_defaults=relationship ='value')
or this
patient.relatives.add(relative, through_defaults=relationship ='value')
example retrieving
patient.relatives.all()