Django - Custom ModelAdmin form not overriding default models - django

I have a model defined
class subnet(models.Model):
subnet_id = models.AutoField(primary_key=True)
subnet_pod = models.ForeignKey(pod, null=True, on_delete=models.SET_NULL, verbose_name='Select Pod')
subnet_number = models.IntegerField(verbose_name='VLAN/SVI Number')
subnet_description = models.CharField(max_length=10, verbose_name='Subnet Description')
LAYER_CHOICES = (
('Layer2', 'Layer2'),
('Layer3', 'Layer3'),
)
subnet_layer = models.CharField(max_length=50, choices=LAYER_CHOICES,verbose_name='Layer2/3')
subnet_ip = models.CharField(max_length=50, verbose_name='Gateway IP/Mask')
vrf = models.ForeignKey(vrf,blank=True, null=True, on_delete=models.SET_NULL, verbose_name='Select VRF')
class Meta:
verbose_name = 'Subnet'
verbose_name_plural = 'Subnets'
def __str__(self):
return self.subnet_number
I want to override the subnet_ip and add a label and placeholder to it using a custom form, so I have:
class subnetForm(forms.ModelForm):
class Meta:
model = subnet
fields = ['subnet_number', 'subnet_description', 'subnet_layer', 'vrf']
widgets = {
'subnet_ip': forms.TextInput(attrs={'placeholder': 'e.g,: x.x.x.x/x'}),
}
However the placeholder does not get applied to the model and does not show in front-end.
I also have a admin.py:
class subnetAdmin(admin.ModelAdmin):
list_display = ('subnet_number','subnet_description','subnet_layer','subnet_ip','vrf')
ordering = ('-subnet_number',)
Any help is appreciated!!

Try this !
class subnetForm(forms.ModelForm):
subnet_number = <use same model field datatype> forms.CharField(label = 'subnet_number', widget = forms.TextInput(attrs = {'placeholder' : 'subnet number'}))
class Meta:
model = subnet
fields = ['subnet_number', __other_fields__]

Related

How to add nested field after creating the ModelSerializer? Not in the class

Basically i want to have fk_inventory as a nested field in StorageRackSerializer but as you guys can see I also need to use StorageRackSerializer in InventorySerializer.
How can i set the field after creating the serializer class?
I have tried creating a fk_inventory field and set it to None and tried to set to InventorySerializer afterwards but didn't work.
class Inventory(models.Model):
inventory_id = models.AutoField(primary_key=True)
fk_building = models.OneToOneField(Store, on_delete=models.CASCADE, unique=True, related_name='inventory')
def __str__(self):
return f"{self.inventory_id}"
class StorageRack(models.Model):
storage_rack_id = models.AutoField(primary_key=True)
quantity = models.IntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(50)])
fk_inventory = models.ForeignKey(Inventory, on_delete=models.CASCADE, related_name="storage_racks")
fk_product_id = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True, related_name="storage_racks")
def __str__(self):
return f"{self.storage_rack_id}"
class StorageRackSerializer(serializers.ModelSerializer):
fk_product_id = ProductSerializer(read_only=True)
fk_inventory = None
class Meta:
model = StorageRack
fields = ('storage_rack_id', 'quantity', 'fk_inventory', 'fk_product_id')
class InventorySerializer(serializers.ModelSerializer):
fk_building = StoreSerializer()
storage_racks = StorageRackSerializer(many=True)
class Meta:
model = Inventory
fields = ('inventory_id', 'fk_building', 'storage_racks')
StorageRackSerializer.fk_inventory = InventorySerializer()
You can add a field 'fk_inventory' in the validated data from SorageRackSerializer
validated_data = StorageRackSerializer(data=data)
validated_data['fk_inventory'] = InventorySerializer().data

KeyError Post DjangoRestFramework

I'm new on Django Rest Framework and when I want to POST data I get a error: KeyError: 'id_area' I do not know what I'm doing wrong. Here's my code:
in my models.py
class Area(models.Model):
id_area = models.AutoField(primary_key=True)
APM = 'apm'
BUSINESS = 'business'
DESARROLLO = 'desarrollo'
SISTEMAS = 'sistemas'
ATENTUSIANOS_CHOICES = (
(APM, 'Apm'),
(BUSINESS, 'Business'),
(DESARROLLO, 'Desarrollo'),
(SISTEMAS, 'Sistemas'),
)
nombre = models.CharField(max_length=255, choices=ATENTUSIANOS_CHOICES)
class Meta:
verbose_name = 'Área'
verbose_name_plural = 'Áreas'
def __str__(self):
return self.nombre
class Atentusiano(models.Model):
id_atentusiano = models.AutoField(primary_key=True)
nombre = models.CharField(max_length=255, blank=False, null=False)
apellido = models.CharField(max_length=255, blank=False, null=False)
correo = models.CharField(max_length=255, blank=False, null=False, unique=True)
anexo = models.CharField(max_length=255, blank=True, null=True)
area = models.ForeignKey(Area, related_name='areas', on_delete=models.CASCADE)
class Meta:
verbose_name = 'Atentusiano'
verbose_name_plural = 'Atentusianos'
ordering = ['nombre']
def __str__(self):
return self.nombre + ' ' + self.apellido
in my serializers.py
class AreaSerializer(serializers.ModelSerializer):
areas = serializers.CharField(read_only=True)
class Meta:
model = Area
fields = ('id_area', 'nombre', 'areas')
class AtentusianoSerializer(serializers.ModelSerializer):
atentusianos = serializers.CharField(read_only=True)
area = serializers.CharField(source='area.nombre', read_only=True)
id_area = serializers.CharField(source='area.id_area')
class Meta:
model = Atentusiano
fields = ['id_atentusiano', 'nombre', 'apellido', 'correo', 'anexo', 'id_area', 'area', 'atentusianos']
def create(self, validated_data):
area_data = validated_data.pop('id_area')
area = models.Area.objects.create(**area_data)
atentusiano = models.Atentusiano.objects.create(area=area, **validated_data)
return atentusiano
And in my views.py
class AtentusianoView(viewsets.ModelViewSet):
queryset = Atentusiano.objects.all()
serializer_class = AtentusianoSerializer
class AreaView(viewsets.ModelViewSet):
queryset = Area.objects.all()
serializer_class = AreaSerializer
The problem is that when I want to Post data, for example:
{
"nombre": "name",
"apellido": "lastname",
"correo": "email#gmail.com",
"anexo": "1364",
"id_area": "1"
}
i got this error area_data = validated_data.pop('id_area')
KeyError: 'id_area'
I need help please
you should pop like this,
class AtentusianoSerializer(serializers.ModelSerializer):
.....
.....
class Meta:
model = Atentusiano
fields = ['id_atentusiano', 'nombre', 'apellido', 'correo', 'anexo', 'id_area', 'area', 'atentusianos']
def create(self, validated_data):
id_area = validated_data.pop('area')['id_area'] # here the correction
area = Area.objects.create(id_area=id_area) # an additional correction
atentusiano = Atentusiano.objects.create(area=area, **validated_data)
return atentusiano
EDIT: As id_area value, you are passing a string instead of an integer which will through another error. Also not,
area = models.Area.objects.create(**area_data)
it should be,
area = Area.objects.create(id_area=id_area)

How to do a relationship using DRF to another table without foreignKey

I can not do relatioships between two tables without relationships.
My models are :
class exampleModel(models.Model):
quantity = models.IntegerField(blank=False, null=True)
comment = models.CharField(max_length=100 , blank=True, null=True)
class Meta:
db_table = "example"
class Logger(models.Model):
id_table = models.IntegerField()
table = models.CharField(max_length=20 , blank=True, null=True)
comment = models.CharField(max_length=100 , blank=True, null=True)
action = models.CharField(max_length=100 , blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = "logger"
I already have filled logger Model, but , I have not be able made the exampleSerializer.
My serializers are:
class LoggerSerializer(serializers.ModelSerializer):
class Meta:
db_table = u'logger'
model = Logger
fields = '__all__'
class exampleSerializer(serializers.ModelSerializer):
last_log = LoggerSerializer(read_only=True)
class Meta:
db_table = 'example'
model = ExampleModel
fields = ( 'id' , 'last_log' , 'quantity')
in logger saves :
id_table : 'primary key of example',
table : 'example'
comment : 'custom comment',
action : "CRUD"
You can query last logger in view, then pass it to serializer in context.
Then do something like:
class exampleSerializer(serializers.ModelSerializer):
last_log = serializers.SerializerMethodField()
class Meta:
db_table = 'example'
model = ExampleModel
fields = ('id', 'last_log', 'quantity')
def get_last_log(self, obj):
last_log = obj.state(self.context['last_log'])
last_log_serializer = LoggerSerializer(last_log)
return last_log_serializer.data
You pass to context, with something like:
exampleSerializer(queryset, context ={'last_log': last_log_object})
Also You can do the query in exampleSerializer:
class exampleSerializer(serializers.ModelSerializer):
last_log = serializers.SerializerMethodField()
class Meta:
db_table = 'example'
model = ExampleModel
fields = ('id', 'last_log', 'quantity')
def get_last_log(self, obj):
logger_queryset =Logger.objects.filter(table = self.Meta.db_table, id_table = obj.id)
return LoggerSerializer(logger_queryset).data

Nested serializers in drf throws error with one to one field

My input json is :
{
"availability": "Current",
"drive_type": [{
"drive_name": "drive1",
"requirements": {
"performance_unit": "by_iops",
}
}]
}
I am getting error Cannot assign "
OrderedDict([('performance_unit', 'Basic')])":
"DriveType.requirements" must be a "Requirements" instance
.I am not able to figure it out to map in create method for one to one fields in tables
Below are my models.py
class ProductLine(models.Model):
availability = models.CharField(max_length=20, blank=True, null=True)
class Meta:
db_table = "product_line"
class DriveType(models.Model):
drive_name = models.CharField(max_length=20, blank=True, null=True)
product_line = models.ForeignKey(ProductLine, related_name="drive_type")
class Meta:
db_table = "drive_type"
class Requirements(models.Model):
performance_unit = models.CharField(max_length=100, blank=True, null=True)
drive_type = models.OneToOneField(DriveType,on_delete=models.CASCADE,primary_key=True,related_name="requirements")
class Meta:
db_table = "requirements"
Serializers.py :
class DriveTypeSerializer(serializers.ModelSerializer):
requirements = RequirementsSerializer(many = True)
class Meta:
model = DriveType
fields = (
"drive_name","workload_type")
class ProductLineSerializer(serializers.ModelSerializer):
drive_type = DriveTypeSerializer(many=True)
class Meta:
model = ProductLine
fields = ('availability', "drive_type")
def create(self, validated_data):
print("validate_data",validated_data)
drive_type_data = validated_data.pop("drive_type")
product_line = ProductLine.objects.create(**validated_data)
for drive_data in drive_type_data:
drive_type = DriveType.objects.create(product_line=product_line, **drive_data)
return product_line
You have one to one relationship of DriveType and Requirements
So remove many = True from DriveTypeSerializer for RequirementsSerializer
class DriveTypeSerializer(serializers.ModelSerializer):
requirements = RequirementsSerializer()
class Meta:
model = DriveType
fields = ("drive_name","workload_type")
Your input json has only one object of requirements not a list

Nested Serializers with multiple tables not working

I have the below tables in models.py.
class ProductLine(models.Model):
availability = models.CharField(max_length=20, blank=True, null=True)
series = models.CharField(max_length=20, blank=True, null=True)
model = models.CharField(max_length=20, blank=True, null=True)
class Meta:
db_table = "product_line"
class DriveType(models.Model):
drive_name = models.CharField(max_length=20, blank=True, null=True)
product_line = models.ForeignKey(ProductLine, related_name="drive_type")
class Requirements(models.Model):
performance_unit = models.CharField(max_length=100, blank=True, null=True)
drive_type = models.OneToOneField(DriveType,on_delete=models.CASCADE,primary_key=True)
class Meta:
db_table = "requirements"
class WorkloadType(models.Model):
workload_type_options = models.CharField(max_length=50, blank=True, null=True)
drive_type = models.OneToOneField(DriveType,on_delete=models.CASCADE,primary_key=True)
class Meta:
db_table = "workload_type"
I have below serializers:
class WorkloadTypeSerializer(serializers.ModelSerializer):
class Meta:
model = WorkloadType
fields = "__all__"
class RequirementsSerializer(serializers.ModelSerializer):
class Meta:
model = Requirements
fields = "__all__"
class DriveTypeSerializer(serializers.ModelSerializer):
requirements = RequirementsSerializer(many = False, read_only = True)
workload_type = WorkloadTypeSerializer(many=False,read_only=True)
class Meta:
model = DriveType
fields = (
"drive_name", "available_drive_type", "capacity", "raid_type", "raid_size", "workload", "workload_percentage",
"raid_groups", "compression", "compression_value","requirements","workload_type")
class ProductLineSerializer(serializers.ModelSerializer):
drive_type = DriveTypeSerializer(many=True, read_only=True)
class Meta:
model = ProductLine
fields = ('availability','series','model','drive_type')
In my views I have this:
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
def get_queryset(self):
return ProductLine.objects.filter(id=self.kwargs.get("pk"))
serializer_class = ProductLineSerializer
I am getting output as below :
{
"availability": "Current",
"series": "3000",
"model": "2000",
"drive_type": [
{
"drive_name": "drive1",
"requirements": {
"drive_type": 2,
"performance_unit": "by_iops",
}
}
]
}
Why I am not able to see WorkLoadType tables data in json where as I am able to see Requirements data . I don't even see the field in json. Nested serializers only support a single relation tables
Answering my own question. Have to use related_name in the models for reverse relationship.
class Requirements(models.Model):
performance_unit = models.CharField(max_length=100, blank=True, null=True)
drive_type = models.OneToOneField(DriveType,on_delete=models.CASCADE,primary_key=True,related_name=requirements)
class Meta:
db_table = "requirements"
class WorkloadType(models.Model):
workload_type_options = models.CharField(max_length=50, blank=True, null=True)
drive_type = models.OneToOneField(DriveType,on_delete=models.CASCADE,primary_key=True,related_name=workload_type)