Behind the scenes, Django appends "_id" to the field name to create
its database column name.
Django ORM adds _id into ForeignKeys, so when I create json format, the column appears with _id at the end, how to remove _id ?
{
"ModelID_id": 1,
"ID": 1,
"DataDefinitionID_id": 1
},
// JSON Builder
ModelDependecy_queryset = Modeldatadependency.objects.values().all()
return Response({"ModelDataDependency": list(ModelDependecy_queryset)},200)
// Model file
class Modeldatadependency(models.Model):
ID = models.AutoField(primary_key=True)
ModelID = models.ForeignKey(Model, models.DO_NOTHING, db_column='ModelID', blank=True, null=True)
DataDefinitionID = models.ForeignKey(Datadefinition, models.DO_NOTHING, db_column='DataDefinitionID', blank=True, null=True)
class Meta:
managed = False
db_table = 'ModelDataDependency'
app_label = 'default'
You can add a method that will return what you need
class Modeldatadependency(models.Model):
ModelID = models.ForeignKey(Model, blank=True, null=True)
DataDefinitionID = models.ForeignKey(Datadefinition, blank=True, null=True)`enter code here`
def get_json(self):
return dict(
ModelID =self.ModelID,
ID =self.id,
DataDefinitionID =self.DataDefinitionID)
Related
I want to join two tables,
i have model :
Employee :
class Employee(models.Model):
employee_identity = models.CharField(max_length=255, blank=True, null=True)
full_name = models.CharField(max_length=255, blank=True, null=True)
place_birth = models.CharField(max_length=255, blank=True, null=True)
date_birth = models.DateField(blank=True, null=True)
role = models.CharField(max_length=255, blank=True, null=True)
no_hp = models.CharField(max_length=255, blank=True, null=True)
address = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'employee'
Penalty :
class Penalty(models.Model):
employee = models.ForeignKey(Employee,on_delete=models.CASCADE)
type = models.CharField(max_length=255, blank=True, null=True)
start_date = models.DateField(blank=True, null=True)
end_date = models.DateField(blank=True, null=True)
doc = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'penalty'
My EmployeeSerializer :
class EmployeeSerializer (serializers.ModelSerializer):
class Meta:
model = Employee
fields = '__all__'
My PenaltySerializer:
class PenaltySerializer (serializers.ModelSerializer):
class Meta:
model = Penalty
fields = ('employee','type','start_date','end_date')
My expected Penalty result :
"results": [
{
"employee": 14871,
"type": "low",
"start_date": "2018-10-15",
"end_date": "2018-10-16",
"employee_identity": "A1738129",
"full_name": "Full name here",
"role": "staff"
}
]
I have tried to using this in my serializer
class PenaltySerializer (serializers.ModelSerializer):
a = EmployeeSerializer(many=True,read_only=True)
class Meta:
model = Penalty
fields = ('employee','type','start_date','end_date','a')
but the result of 'a' not showed up.
I think this might help
class PenaltySerializer (serializers.ModelSerializer):
employee_identity = serializers.CharField(source="employee.employee_identity")
full_name = serializers.CharField(source="employee.full_name")
role = serializers.CharField(source="employee.role")
class Meta:
model = Penalty
fields = (
'employee',
'type',
'start_date',
'end_date',
'employee_identity',
'full_name',
'role'
)
You can do something like this in your serializer:
class PenaltySerializer (serializers.ModelSerializer):
employee = serializers.SerializerMethodField()
class Meta:
model=Penalty
fields = '__all__'
def get_employee(self, object):
return EmployeeSerializer(object.employee.all(), many=True).data
This is my models.py:
class UnitOfMeasurement(models.Model):
active = models.BooleanField(default=True)
name = models.CharField(max_length=255)
measurement_type = models.CharField(max_length=255)
def __str__(self):
return self.name
class Category(models.Model):
name = models.CharField(max_length=250)
abbreviation=models.CharField(max_length=10)
active = models.BooleanField(default=True)
description=models.CharField(max_length=500,blank=True, null=True)
def __str__(self):
return self.name
class Product(models.Model):
active = models.BooleanField(default=True)
bar_code = models.CharField(max_length=50, blank = True, null = True)
name = models.CharField(max_length=250)
category = models.ForeignKey(
Category, on_delete=models.CASCADE, related_name='product')
brand = models.CharField(max_length=250)
model = models.CharField(max_length=250)
tag = models.CharField(max_length=250, null=True)
remarks = models.TextField(null=True)
gstcode = models.ForeignKey(
GSTCode, on_delete=models.CASCADE, related_name='product', null=True)
unit_of_measurement = models.ForeignKey(
UnitOfMeasurement, on_delete=models.DO_NOTHING, related_name='category')
# picture
objects=ProductManager()
# select the product where active=true & quantity<0
def __str__(self):
return self.name
So how do I need to code my serializers and views in order to get the data that returns name, category, brand, model, tag from Product Model and name from Category Model and also name and measurement_type from UnitOfMeasurement Model?
You can select fields from model in serializer as below example code for UnitOfMeasurement and use this serializer for get(retrieve) request.
class UnitOfMeasurementSerializer(serializers.ModelSerializer):
class Meta:
model = UnitOfMeasurement
fields = ["name", "measurement_type"]
Same thing you can do for rest of models.
Views depends on your use case.
Suppose i have two models:
class Region(models.Model):
region_name = models.CharField(
max_length=50, null=False, blank=False, unique=True, verbose_name="Region Name"
)
def __str__(self):
return self.region_name
class Meta:
verbose_name_plural = "Regions"
class Country(models.Model):
region_id = models.ForeignKey(
Region,
null=True,
blank=True,
on_delete=models.CASCADE,
verbose_name="Region id",
)
country_name = models.CharField(
max_length=50, unique=True, null=False, blank=False, verbose_name="Country Name"
)
def __str__(self):
return self.country_name
class Meta:
verbose_name_plural = "Countries"
Now, when i access the country model through Djnago REST Framework, as /api/countries
I get country_name and region_id for example
[
{
"id": 1,
"country_name":"Taiwan",
"region_id": 1
},
...
...
]
Is there any way to get the result like:
[
{
"id": 1,
"country_name":"Taiwan",
"region_id": {
id: 1,
region_name: "Asia",
}
},
...
...
]
I have tried nested serializer example as on the DRF website, but it returns a list of countries if we get the regions api.
like:
[
{
"id": 1,
"region_name":"Asia",
"countries":
[
"Taiwan",
"Japan",
"Vietnam",
...
]
},
...
...
]
I need to know the region name of the country in one api get request. Right now i am using 2 requests. One to get country, and then get region name from region id.
This is my model and serializer if i use nested serializer.
class Region(models.Model):
region_name = models.CharField(
max_length=50, null=False, blank=False, unique=True, verbose_name="Region Name"
)
def __str__(self):
return self.region_name
class Meta:
verbose_name_plural = "Regions"
class Country(models.Model):
region_id = models.ForeignKey(
related_name="countries"
Region,
null=True,
blank=True,
on_delete=models.CASCADE,
verbose_name="Region id",
)
country_name = models.CharField(
max_length=50, unique=True, null=False, blank=False, verbose_name="Country Name"
)
class CountrySerializer(serializers.ModelSerializer):
class Meta:
model = Country
fields = "__all__"
class RegionSerializer(serializers.ModelSerializer):
countries = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='country_name'
)
class Meta:
model = Region
fields = ["id", "region_name", "countries"]
The reason you only get the slugs of the related Countrys is because you use the SlugRelatedField, that will thus list the slugs of the Countrys.
The trick is to make extra serializers that will serializer the related object(s). For example:
class ShallowRegionSerializer(serializers.ModelSerializer):
class Meta:
model = Region
fields = '__all__'
class CountrySerializer(serializers.ModelSerializer):
region_id = ShallowRegionSerializer()
class Meta:
model = Country
fields = '__all__'
class CountryRegionSerializer(serializers.ModelSerializer):
class Meta:
model = Country
fields = '__all__'
class RegionSerializer(serializers.ModelSerializer):
countries = CountryRegionSerializer(
many=True,
read_only=True
)
class Meta:
model = Region
fields = ['id', 'region_name', 'countries']
Now you can make use of the CountrySerializer and the RegionSerializer. When serializing objects, it will use other serializers, like the ShallowRegionSerializer and CountryRegionSerializer to serialize related object(s).
I'd like to use two different primary keys in my DRF database app. By default Django "create" id as PK but when I'm trying to define new field in model (uuid = models.UUIDField (primary_key=True, default=uuid.uuid4, editable=False), default id field is not defined (in DB exist only uuid).
How can I initialize both of them?
I can mention that I didn't define id field in my model because it is (or should be - as I suppose) adding by DRF.
class Store(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4,
editable=False)
name = models.CharField(max_length=100, blank=False)
url = models.URLField(max_length=300, blank=False)
country = models.CharField(max_length=100, blank=True)
Primary key
In the relational model of databases, a primary key is a specific choice of a minimal set of attributes (columns) that uniquely specify a tuple (row) in a relation (table).
So, you can either use default primary key id or uuid (your choice).
If you want both then use unique=True instead.
class Store(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100, blank=False)
url = models.URLField(max_length=300, blank=False)
country = models.CharField(max_length=100, blank=True)
For your case you can change your model as
from django.db.models.fields import AutoField
from django.db.models.fields import checks
from django import models
class AutoFieldNonPrimary(AutoField):
def _check_primary_key(self):
if self.primary_key:
return [
checks.Error(
"AutoFieldNonPrimary must not set primary_key=True.",
obj=self,
id="fields.E100",
)
]
else:
return []
class Store(models.Model):
id = models.AutoFieldNonPrimary(unique=True)
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=100, blank=False)
url = models.URLField(max_length=300, blank=False)
country = models.CharField(max_length=100, blank=True)
I am using DRF to serialize and have the api endpoints to display json data.
I have 2 models -
class FooOne(models.Model):
field_a = models.CharField(max_length=255, null=False)
field_b = models.CharField(max_length=255, null=False)
field_c = models.CharField(max_length=255, null=False)
class FooTwo(models.Model):
field_fk = models.ForeignKey(FooOne)
field_d = models.CharField(max_length=255, null=False)
field_e = models.CharField(max_length=255, null=False)
these are my serializer classes -
class FooOneSerializer(serializers.ModelSerializer):
class Meta:
model = FooOne
fields = (field_a, field_b, field_c)
class FooTwoSerializer(serializers.ModelSerializer):
field_fk = FooOneSerializer()
class Meta:
model = FooTwo
fields = (field_fk, field_d, field_e)
FooTwoSerializer will return data with field_fk as a nested dictionary. What i want to is to return other fields of FooOneSerialzer that arent foreign key to FooTwo and append it the final rendered result of FooTwoSerializer.
How do i go about this?
If I understand well, you want concatenate the results of FooOneSerailizer and all fields of FooTwoSerializer. You can do so by overriding to_represetation() method.
class FooTwoSerializer(serializers.ModelSerializer):
class Meta:
model = FooTwo
fields = (field_d, field_e)
def to_representation(self, instance):
# get OrderedDict with original fields
response = super(FooTwoSerializer, self).to_representation(instance)
# get OrderedDict with foreign foo_one data
foo_one = FooOneSerializer(instance.field_fk).data
# set this fields to original data
for key in foo_one:
response[key] = foo_one[key]
return response