Django nested serializers not being applied to views - python

I'm currently developing my django backend app defining some models for vehicles, but I've been unable to serialize the views for my purpose, I've attempted a couple changes but nothing works yet:
Models.py
class vehicles_brand(models.Model):
pk_idbrand= models.AutoField(db_column='PK_IdBrand', primary_key=True) # Field name made lowercase.
fk_idcountry= models.ForeignKey(locations_country, on_delete= models.CASCADE, db_column='FK_IdLocationCountry', related_name='Country')
name = models.CharField(max_length=20, default=None, null=True)
logo = models.ImageField(upload_to=upload_photo_brand, null=True, blank=True)
class Meta:
db_table = 'vehicles_brand'
verbose_name_plural = "Vehicle Brands"
def __str__(self):
return self.name
class vehicles_model(models.Model):
pk_idmodel = models.AutoField(db_column='PK_IdModel', primary_key=True) # Field name made lowercase.
name = models.CharField(max_length=20, default=None)
fk_idbrand= models.ForeignKey(vehicles_brand, on_delete= models.CASCADE, db_column='FK_IdVehicleBrand', related_name='Brand')
class Meta:
db_table = 'vehicles_model'
verbose_name_plural = "Vehicle Models"
# def __int__(self):
# return '{}'.format(self.pk_idmodel)
class vehicles_vehicle(models.Model):
pk_idvehicle = models.AutoField(db_column='PK_IdVehicle', primary_key=True) # Field name made lowercase.
fk_idmodel= models.ForeignKey(vehicles_model, on_delete= models.CASCADE, db_column='FK_IdVehicleModel', related_name="vehicle_model")
fk_idbrand= models.ForeignKey(vehicles_brand, on_delete= models.CASCADE, db_column='FK_IdVehicleBrand', related_name="vehicle_brand")
fk_idlocation= models.ForeignKey(locations_city, on_delete= models.CASCADE,
name = models.CharField(max_length=20, default=None, null=True)
class Meta:
db_table = 'vehicles_vehicle'
verbose_name_plural = "Vehicles"
# def __str__(self):
# return self.pk_idvehicle
Serializers.py
from rest_framework import serializers
from vehicles.models import vehicles_vehicle, vehicles_model, vehicles_brand
class brandSerializer(serializers.ModelSerializer):
class Meta:
model = vehicles_brand
fields = ['name']
depth = 3
class modelSerializer(serializers.ModelSerializer):
class Meta:
model = vehicles_model
fields = ['name', 'body', 'cilinder_capacity', 'traction', 'traction_measure', 'fuel_consumption', 'fuel_consumption_measure', 'extras']
depth = 3
class vehicleSerializer(serializers.ModelSerializer):
fk_idbrand = brandSerializer(many=True, read_only=True)
fk_idmodel = modelSerializer(many=True, read_only=True)
class Meta:
model = vehicles_vehicle
fields = ('pk_idvehicle', 'year', 'price', 'fk_idbrand', 'fk_idmodel')
depth = 3
Views.py
from vehicles.serializers import vehicleSerializer,brandSerializer,modelSerializer
from vehicles.models import (vehicles_vehicle, vehicles_brand, vehicles_model)
#api_view(('GET',))
def get_all_brands(request):
serializer_class = brandSerializer
data = vehicles_brand.objects.all().values()
return Response(data)
#api_view(('GET',))
def get_all_vehicles(request):
serializer_class = vehicleSerializer
data = vehicles_vehicle.objects.all().values()
return Response(data)
#api_view(('GET',))
def get_vehicle(request,id):
serializer_class = vehicleSerializer
data = vehicles_vehicle.objects.get(pk_idvehicle = id)
return Response(data)
But I keep receiving the entire object with all the fields and key numbers for all my views, for example in brand:
{
"pk_idbrand": 1,
"fk_idcountry_id": 1,
"name": "Chevrolet",
"logo": null
},
{
"pk_idbrand": 2,
"fk_idcountry_id": 1,
"name": "Dodge",
"logo": ""
},
Thanks in advance for any hint or help

your code:
#api_view(('GET',))
def get_all_brands(request):
serializer_class = brandSerializer
data = vehicles_brand.objects.all().values()
return Response(data)
changes to be made:
#api_view(('GET',))
def get_all_brands(request):
data = vehicles_brand.objects.all().values()
serializers = brandSerializer(data ,many=True)
return Response(serializers.data)

Related

django.db.utils.IntegrityError: null value in column "auto_id" of relation "university_university" violates not-null constraint

I am getting a integrity error, I have tried adding null=True to auto id field then its working but auto_id field must not be blank=True or null=True.These models are given by my superiors I am finding this hard to understand
This is the core app models.py
import uuid
from django.db import models
from django.db.models import Max
from django.utils import timezone
from decimal import Decimal
from django.utils.translation import gettext_lazy as _
from django.core.validators import MinValueValidator
from core.utils import DictField
from django.contrib.auth import get_user_model
from django.contrib.humanize.templatetags.humanize import naturaltime
def basedata(self, request):
# Check is create
if self._state.adding:
self.auto_id = (self.__class__.objects.aggregate(max_auto_id=Max('auto_id')).get('max_auto_id') or 0) + 1
if request.user.is_authenticated:
self.creator = request.user
# If updating
if request.user.is_authenticated:
self.updater = request.user
self.date_updated = timezone.now()
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
auto_id = models.PositiveIntegerField(db_index=True, unique=True)
creator = models.ForeignKey(get_user_model(), blank=True, related_name="creator_%(class)s_objects", limit_choices_to={'is_active': True}, on_delete=models.CASCADE)
updater = models.ForeignKey(get_user_model(), blank=True, related_name="updater_%(class)s_objects", limit_choices_to={'is_active': True}, on_delete=models.CASCADE)
date_added = models.DateTimeField(db_index=True, auto_now_add=True)
date_updated = models.DateTimeField(auto_now_add=True)
is_deleted = models.BooleanField(default=False)
class Meta:
abstract = True
def delete(self):
self.is_deleted = True
self.save()
def delete_with_user(self, user):
self.is_deleted = True
user = self.user
user.username = user.username + '_deleted_' + str(self.id)
user.save()
self.save()
#property
def date_added_natural(self):
return naturaltime(self.date_added)
class Mode(models.Model):
readonly = models.BooleanField(default=False)
maintenance = models.BooleanField(default=False)
down = models.BooleanField(default=False)
class Meta:
db_table = 'mode'
verbose_name = _('mode')
verbose_name_plural = _('mode')
ordering = ('id',)
class Admin:
list_display = ('id', 'readonly', 'maintenance', 'down')
def __str__(self):
return str(self.id)
class AppUpdate(models.Model):
date_added = models.DateTimeField(db_index=True, auto_now_add=True)
app_version = models.CharField(max_length=16)
force_upgrade = models.BooleanField(default=False)
recommended_upgrade = models.BooleanField(default=False)
ios_app_version = models.CharField(max_length=16)
ios_force_upgrade = models.BooleanField(default=False)
ios_recommended_upgrade = models.BooleanField(default=False)
class Meta:
db_table = 'app_update'
verbose_name = _('App update')
verbose_name_plural = _('App updates')
ordering = ('id',)
def __str__(self):
return str(self.id)
This is the university models.py
from django.db import models
from core.models import BaseModel
from versatileimagefield.fields import VersatileImageField
# Create your models here.
class Graduation(BaseModel):
name = models.CharField(max_length=200)
class Meta:
db_table = 'university_graduation'
verbose_name = ('Graduation')
verbose_name_plural = ('Graduation')
ordering = ('auto_id',)
def __str__(self):
return str(self.name)
class University(BaseModel):
title = models.CharField(max_length=200)
location = models.CharField(max_length=200)
location_url = models.URLField()
estd = models.CharField(max_length=4)
ranking = models.CharField(max_length=4)
intake = models.CharField(max_length=3)
acceptance_rate = models.CharField(max_length=3)
teacher_ratio = models.CharField(max_length=3)
about_university = models.TextField()
description = models.TextField()
graduation = models.ManyToManyField(Graduation)
logo = VersatileImageField('Logo', upload_to="university/logo")
image = VersatileImageField('Image', upload_to="university/image")
class Meta:
db_table = 'university_university'
verbose_name = ('University')
verbose_name_plural = ('University')
ordering = ('auto_id',)
def __str__(self):
return str(self.title)
class AdmissionRequirments(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
auto_id = models.PositiveIntegerField(db_index=True, unique=True)
date_added = models.DateTimeField(db_index=True, auto_now_add=True)
date_updated = models.DateTimeField(auto_now_add=True)
university = models.ForeignKey(University, limit_choices_to={'is_deleted': False}, on_delete=models.CASCADE)
requirement = models.CharField(max_length=200)
class Meta:
db_table = 'university_admission_requirements'
verbose_name = ('Admission Requirements')
verbose_name_plural = ('Admission Requirements')
ordering = ('auto_id',)
def __str__(self):
return str(self.id)
class Scholarship(BaseModel):
title = models.CharField(max_length=200)
eligibility = models.CharField(max_length=200)
applicability = models.CharField(max_length=200)
graduation = models.ManyToManyField(Graduation)
university = models.ManyToManyField(University)
class Meta:
db_table = 'university_scholarship'
verbose_name = ('Scholarship')
verbose_name_plural = ('Scholarship')
ordering = ('auto_id',)
def __str__(self):
return str(self.title)
This is the university form.py
from django.forms import forms
from university.models import University, Graduation
from django.contrib.auth.models import User
from django.contrib.auth import get_user
class CreateUniversityForm(forms.Form):
class Meta:
model = University
fields = '__all__'
def save(self):
user = self.cleaned_data.get("user")
university = University(
auto_id = self.cleaned_data.get('id'),
title = self.cleaned_data.get('title'),
location = self.cleaned_data.get('location'),
location_url = self.cleaned_data.get('location_url'),
estd = self.cleaned_data.get('estd'),
ranking = self.cleaned_data.get('ranking'),
intake = self.cleaned_data.get('intake'),
acceptance_rate = self.cleaned_data.get('acceptance_rate'),
teacher_ratio = self.cleaned_data.get('teacher_ratio'),
about_university = self.cleaned_data.get('about_university'),
description = self.cleaned_data.get('description'),
logo = self.cleaned_data.get('logo'),
image = self.cleaned_data.get('image')
)
graduation = Graduation.objects.get(name=self.cleaned_data.get("graduation"))
university.set_graduation = graduation
university.set_creator = user
university.set_updator = user
university.save()
return university
This is my university view.py to create a university
def create_university(request):
if request.method == 'POST':
user = get_user(request)
logo = request.FILES.get('logo')
image = request.FILES.get('image')
auto_id = int(request.POST.get('id'))
title = request.POST.get('title')
graduation = "berlin"
location = request.POST.get('location')
location_url = request.POST.get('location_url')
established = request.POST.get('established')
ranking = request.POST.get('ranking')
intake = request.POST.get('intake')
acceptance_rate = request.POST.get('acceptance')
teacher_ratio = request.POST.get('teacher')
about_university = request.POST.get('about')
description = request.POST.get('description')
data = {
'user': user,
'title': title,
'id': auto_id,
'location': location,
'location_url': location_url,
'estd': established,
'ranking': ranking,
'intake': intake,
'acceptance_rate': acceptance_rate,
'teacher_ratio': teacher_ratio,
'about_university': about_university,
'description': description,
'logo': logo,
'image': image,
'graduation': graduation}
print(data)
create_university_form = CreateUniversityForm(data=data)
if create_university_form.is_valid():
university = create_university_form.save()
context = {
'title': university.title
}
return JsonResponse(context)
else:
context = {
"validationerror": "validation error"
}
return JsonResponse(context)
university model admin view
All i wanted to do is to create a new univerisity object but this auto_id is killing me, also i cant understand this BaseModel system
File "C:\Users\abinp\Documents\projects\tegain\venv\lib\site-packages\django\db\backends\utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: null value in column "auto_id" of relation "university_university" violates not-null constraint
DETAIL: Failing row contains (c496cf2f-2966-49f3-b2d4-9efa4f3323b4, null, 2022-08-08 10:36:59.869385+00, 2022-08-08 10:36:59.869385+00, f, null, null, null, null, null, null, null, null, null, null, , , null, null).
As the error says, you have a null value in the ID column.
auto_id = models.PositiveIntegerField(db_index=True, unique=True)
You have PositiveIntegerField, that means that you have to fill it and you're probably not doing that in forms. For ID you should always use AutoField.
So it returns null because there is nothing in your auto_id variable. I think replace this with AutoField should solve the problem.
Documentation search for AutoField:
https://docs.djangoproject.com/en/4.1/ref/models/fields/

How to get field name instead of foreign id in django

In my django app, i have four model tables linked using foreign keys, the problem is, when i make a query for any model table, the fields that are linked through foreign keys are returned as id's instead of the name.
My way does not work.
My customers models.py file
1st model
class Customer(models.Model):
name = models.CharField(max_length=50)
phone = models.CharField(max_length=20, unique=True)
email = models.EmailField(max_length=255, unique=True, blank=True)
image = models.ImageField(default='default.png', upload_to='customer_photos/%Y/%m/%d/')
data_added = models.DateField(default=datetime.now, blank=True)
def __str__(self):
return self.name
2nd model
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="customer_ship_address")
description = models.TextField(blank=True)
frequent_customer = models.BooleanField(default=False)
address = models.CharField(max_length=50, blank=True)
zip_code = models.CharField(max_length=12, blank=True)
location = models.CharField(max_length=255)
def __str__(self):
return self.customer.name
3rd model - PaymentInvoice
class paymentInvoice(models.Model):
shipping_address_owner = models.ForeignKey(
ShippingAddress, on_delete=models.CASCADE, related_name="customer_invoice")
product = models.ManyToManyField(
Product, related_name='product_invoice')
mode = models.CharField(max_length=20, choices=paymentMode.choices, default=paymentMode.MPESA)
date = models.DateField(default=datetime.now)
invoice_id = models.CharField(
max_length=50, unique=True, default=increment_invoice_number)
quantity = models.PositiveSmallIntegerField()
status = models.CharField(
max_length=20, choices=paymentStatus.choices, default=paymentStatus.PENDING)
payment_made = models.DecimalField(max_digits=20, decimal_places=2)
def __str__(self):
return self.shipping_address_owner.customer.name
My Products models.py file
class Product(models.Model):
slug = models.CharField(max_length=200, unique=True)
name = models.CharField(max_length=200)
available = models.BooleanField(default=True)
description = models.TextField(blank=True)
image = models.ImageField(default='default_product.jpg', upload_to='product_photos')
category = models.CharField(max_length=200)
qty_amount = models.CharField(
max_length=20, choices=Qty_Choices, default='250ml')
price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.name
My PaymentInvoice views.py file
class paymentInvoiceListCreateView(ListCreateAPIView):
"""
ListCreateAPIView executes both 'GET' and 'POST' requests. i.e listing a queryset or creating a model instance.
"""
serializer_class = paymentInvoiceSerializer
queryset = paymentInvoice.objects.all().order_by(
'-date').values(shipping_address_owner__customer)
When i make the above query the api returns the following, where the product field and shipping_address_owner field are just id's. I need there respective names instead.
{
"count": 6,
"next": null,
"previous": null,
"results": [
{
"id": 9,
"mode": "Mpesa",
"date": "2020-07-27",
"invoice_id": "INV-0006",
"quantity": 1,
"status": "Pending",
"payment_made": "500.00",
"shipping_address_owner": 9,
"product": [
1
]
},
EDIT: paymentInvoiceSerializer
class paymentInvoiceSerializer(serializers.ModelSerializer):
class Meta:
model = paymentInvoice
fields = '__all__'
You need to make some changes to your serializer.
If you just need the name and nothing more:
class paymentInvoiceSerializer(serializers.ModelSerializer):
product = serializers.SerializerMethodField()
shipping_address_owner = serializers.SerializerMethodField()
class Meta:
model = paymentInvoice
fields = '__all__'
def get_product(self, instance):
names = []
for product in instance.product.all():
names.append(product.name)
return names
def get_shipping_address_owner(self, instance):
return instance.shipping_address_owner.customer.name
You can also create different serializer for each model and pass them to their fields to get the full serialized data for them. It would be something like this:
ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
And then in your payment serializer:
class paymentInvoiceSerializer(serializers.ModelSerializer):
product = ProductSerializer()
class Meta:
model = paymentInvoice
fields = '__all__'
You can do the same for shipping_address_owner.
You can try like this in your serializer.
class paymentInvoiceSerializer(serializers.ModelSerializer):
shipping_address_owner = serializers.CharField(source='shipping_address_owner.customer')
class Meta:
model = paymentInvoice
fields = ['shipping_address_owner',...]

how to assign the foreign keys for this DRF nested serializer

I'm working on an app that receives clothes "vendor, product type and sizes" from an external source that i want to save, then update the Size Charts later.
but i'm not getting it to successfully save and update
here's my Models.py:
class Vendor(models.Model):
name = models.CharField(max_length=50, null=False, blank=False)
store_slug = models.CharField(max_length=100, null=False, blank=False)
is_from_user = models.NullBooleanField(null=False, default=True)
class Meta:
ordering = ('name',)
verbose_name_plural = 'Vendors'
def __str__(self):
return self.name
class ProductType(models.Model):
vendor = models.ForeignKey(Vendor,related_name='producttypes', on_delete =models.CASCADE, null=False)
name = models.CharField(max_length=50, null=False, blank=False)
country = models.CharField(max_length=50, default="US", null=False, blank=True)
gender = models.CharField(max_length=50, default="NONE", null=False)
class Meta:
ordering = ('name',)
verbose_name_plural = 'ProductTypes'
def __str__(self):
return self.name + ' | ' + self.vendor.name
class Size(models.Model):
producttype = models.ForeignKey(ProductType,related_name='sizes', on_delete =models.CASCADE, null=False)
name = models.TextField(max_length=50, null=False, blank=False)
#ready = models.NullBooleanField(default=False)
class Meta:
ordering = ('name',)
verbose_name_plural = 'Sizes'
def __str__(self):
return self.name + ' | ' + self.producttype.name
class Chart(models.Model):
size = models.ForeignKey(Size,related_name='charts', on_delete =models.CASCADE, null=False)
bust = models.DecimalField(max_digits=5, decimal_places=2, default=0.0, null=True, blank=True)
hip = models.DecimalField(max_digits=5, decimal_places=2, default=0.0, null=True, blank=True)
waist = models.DecimalField(max_digits=5, decimal_places=2, default=0.0, null=True, blank=True)
unit = models.CharField(max_length=50, default="CM", null=False, blank=True)
class Meta:
ordering = ('size',)
verbose_name_plural = 'Charts'
def __str__(self):
return self.unit + ' Chart of | '+ self.size.name + ' | '
and in my serializers.py :
class ChartSerializer(serializers.ModelSerializer):
class Meta:
model = Chart
fields = ('id', 'hip', 'bust', 'waist' , 'unit' ,'size')
class SizeSerializer(serializers.ModelSerializer):
charts = ChartSerializer( many=True)
class Meta:
model = Size
fields = ('id', 'name' ,'producttype', 'charts' )
class ProductTypeSerializer(serializers.ModelSerializer):
sizes = SizeSerializer( many=True)
class Meta:
model = ProductType
fields = ('id', 'name', 'country', 'gender','vendor', 'sizes')
class VendorSerializer(serializers.ModelSerializer):
producttypes = ProductTypeSerializer(many=True)
class Meta:
model = Vendor
fields = ('id', 'name', 'store_slug', 'producttypes')
def run_validators(self, value):
for validator in self.validators:
if isinstance(validator, validators.UniqueTogetherValidator):
self.validators.remove(validator)
super(VendorSerializer, self).run_validators(value)
def create(self, validated_data):
producttypes = validated_data.pop('producttypes')
v = Vendor.objects.get_or_create(**validated_data)
for producttype in producttypes:
sizes = producttype.pop('sizes')
p = ProductType.objects.get_or_create(vendor=v, **producttype)
for size in sizes:
charts = size.pop('charts')
s = Size.objects.get_or_create(producttype=p, **size)
for chart in charts:
c = Chart.objects.get_or_create(size=size, **chart)
return v
and my views.py:
class VendorViewSet(viewsets.ModelViewSet):
queryset = Vendor.objects.all()
def get_serializer_class(self):
if self.request.method in ['GET']:
return VendorReadSerializer
return VendorSerializer
class ProductTypeViewSet(viewsets.ModelViewSet):
queryset = ProductType.objects.all()
def get_serializer_class(self):
if self.request.method in ['GET']:
# Since the ReadSerializer does nested lookups
# in multiple tables, only use it when necessary
return ProductTypeReadSerializer
return ProductTypeSerializer
class SizeViewSet(viewsets.ModelViewSet):
queryset = Size.objects.all()
def get_serializer_class(self):
if self.request.method in ['GET']:
return SizeReadSerializer
return SizeSerializer
class ChartViewSet(viewsets.ModelViewSet):
queryset = Chart.objects.all()
def get_serializer_class(self):
if self.request.method in ['GET']:
return ChartReadSerializer
return ChartSerializer
and here is what i think the the post request should be
data = {
"name": "Adidas",
"store_slug": "slugexamplecom",
"producttypes": [
{
"name": "short",
"gender": "female",
"countr":"US",
"sizes": [
{
"name": "Small",
"charts":[{"unit":"CM",}]
},
{
"name":"Medium",
"charts":[{"unit":"CM","hip":"10","bust":"10","waist":"10"}]
},
{
"name":"Large",
"charts":[{"unit":"IN","hip":"20","bust":"20","waist":"20"}]
}
]
},
]}
My Case:
here is what i receive from an external source,
that i want to iterate over their sizes and create a not-ready chart
for later update on my dashboard.
all the fields should be updatable.
{"name": "Adidas",
"store_slug": "aSlug",
"producttypes": [{
"name": "short",
"gender": "female",
"sizes": [{"name":"small"},{"name":"Medium"},{"name":"Large"} ]}
]}
what am i doing wrong ?
How do i save and update ? and assign the foreign Key
#Currently the serializer is not valid
#if i remove the foreign keys fields i get a valid serializer with this error
#TypeError: int() argument must be a string, a bytes-like object or a number, not 'Vendor'

How to save three related models in one DRF endpoint?

I have 4 related models and I need to implement the functionality to consistently create instances of these models in a database in one post query. For this I use override of the APIView class post method.
models
class VendorContacts(models.Model):
contact_id = models.AutoField(primary_key=True)
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE)
contact_name = models.CharField(max_length=45, blank=True)
phone = models.CharField(max_length=45, blank=True)
email = models.CharField(max_length=80, blank=True, unique=True)
class Meta:
db_table = 'vendor_contacts'
class VendorModuleNames(models.Model):
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE, primary_key=True)
module = models.ForeignKey(Modules, models.DO_NOTHING)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'vendor_module_names'
unique_together = (('vendor', 'module'),)
class Vendors(models.Model):
COUNTRY_CHOICES = tuple(COUNTRIES)
vendorid = models.AutoField(primary_key=True)
vendor_name = models.CharField(max_length=45, unique=True)
country = models.CharField(max_length=45, choices=COUNTRY_CHOICES)
nda = models.DateField(blank=True, null=True)
user_id = models.ForeignKey('c_users.CustomUser', on_delete=models.PROTECT)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'vendors'
unique_together = (('vendorid', 'timestamp'),)
class Modules(models.Model):
MODULES_NAME =tuple(MODULES)
mid = models.AutoField(primary_key=True)
module_name = models.CharField(max_length=50, choices=MODULES_NAME)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'modules'
unique_together = (('mid', 'timestamp'),)
serializer.py
class VendorsSerializer(serializers.ModelSerializer):
class Meta:
model = Vendors
fields = ('vendor_name',
'country',
'nda',)
class VendorContactSerializer(serializers.ModelSerializer):
class Meta:
model = VendorContacts
fields = (
'contact_name',
'phone',
'email',)
class VendorModulSerializer(serializers.ModelSerializer):
class Meta:
model = VendorModuleNames
fields = ('module',)
class ModulesSerializer(serializers.ModelSerializer):
class Meta:
model = Modules
fields = ('module_name', )
views.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
def post(self, request, *args, **kwargs):
vendor_serializer = VendorsSerializer(data=request.data)
vendor_contact_serializer = VendorContactSerializer(data=request.data)
vendor_modules_serializer = VendorModulSerializer(data=request.data)
module_serializer = ModulesSerializer(data=request.data)
try:
vendor_serializer.is_valid(raise_exception=True) \
and vendor_contact_serializer.is_valid(raise_exception=True) \
and vendor_modules_serializer.is_valid(raise_exception=True) \
and module_serializer.is_valid(raise_exception=True)
vendor_serializer.save(user_id=request.user)
# ....
# Some new logic here ????
# ...
except ValidationError:
return Response({"errors": (vendor_serializer.errors,
vendor_contact_serializer.errors,
vendor_modules_serializer.errors
)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)
There is no problem saving one Vendor model, but I can't imagine how to save cascading all related models in a single request.
save returns the newly saved object, which you can then pass into the subsequent save() methods:
vendor = vendor_serializer.save(user_id=request.user)
module = module_serializer.save()
vendor_module = vendor_modules_serializer.save(module=module, vendor=vendor)
vendor_contact = vendor_contact_serializer.save(vendor=vendor)

Django-rest-framework drf-extensions: Nested routers/urls are not filtering

I can't get the my Router to filter my requests based on the "parents_query_lookup".
Here's my code:
urls.py:
from rest_framework_extensions.routers import ExtendedSimpleRouter
from .views import OrganizationViewSet, GroupViewSet, BootGroupViewSet
router = ExtendedSimpleRouter()
(router.register(r'organizations', OrganizationViewSet,
base_name='organization')
.register(r'groups', GroupViewSet, base_name='organizations-group',
parents_query_lookups=['resource__organization'])
.register(r'boot_groups', BootGroupViewSet,
base_name='organizations-groups-boot_group',
parents_query_lookups=['group__resource__organization', 'group']))
urlpatterns = router.urls
views.py:
from rest_framework.viewsets import ModelViewSet
from rest_framework_extensions.mixins import NestedViewSetMixin
from .models import Organization, OrganizationSerializer, \
Group, GroupSerializer, BootGroup, BootGroupSerializer
class OrganizationViewSet(NestedViewSetMixin, ModelViewSet):
queryset = Organization.objects.all()
serializer_class = OrganizationSerializer
class GroupViewSet(NestedViewSetMixin, ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
class BootGroupViewSet(NestedViewSetMixin, ModelViewSet):
queryset = BootGroup.objects.all()
serializer_class = BootGroupSerializer
enums.py:
class ResourceTypeEnum:
RESOURCE_TYPE_GROUP = 'group'
RESOURCE_TYPE_VM = 'vm'
RESOURCE_TYPE_CHOICES = (
(RESOURCE_TYPE_GROUP, RESOURCE_TYPE_GROUP),
(RESOURCE_TYPE_VM, RESOURCE_TYPE_VM)
)
models.py:
from django.db.models import Model
from rest_framework.serializers import ModelSerializer
from .enums import ResourceTypeEnum
class Organization(Model):
organization_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
parent = models.ForeignKey('self', blank=True, null=True)
class Meta:
unique_together = (("name", "parent"))
verbose_name = "Organization"
verbose_name_plural = "Organizations"
app_label = 'api_manager'
db_table = 'organization'
def __unicode__(self):
return self.name
class OrganizationSerializer(ModelSerializer):
class Meta:
model = Organization
fields = ('name', 'parent')
depth = 2
class Resource(Model):
resource_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=55)
type = models.CharField(
max_length=5, choices=ResourceTypeEnum.RESOURCE_TYPE_CHOICES)
organization = models.ForeignKey(Organization)
class Meta:
verbose_name = "Resource"
verbose_name_plural = "Resources"
app_label = 'api_manager'
db_table = 'resource'
def __unicode__(self):
return self.name
class ResourceSerializer(ModelSerializer):
class Meta:
model = Resource
fields = ('name', 'type', 'organization')
depth = 2
class Group(Model):
resource = models.OneToOneField(Resource, primary_key=True)
is_consistent = models.BooleanField()
parent = models.ForeignKey('self', blank=True, null=True)
class Meta:
verbose_name = "Group"
verbose_name_plural = "Groups"
app_label = 'api_manager'
db_table = 'group'
def __unicode__(self):
return "%s: %s" % (self.resource.organization, self.resource)
class GroupSerializer(ModelSerializer):
class Meta:
model = Group
fields = ('resource', 'is_consistent', 'parent')
depth = 2
class BootGroup(Model):
boot_group_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
boot_order = models.PositiveSmallIntegerField(default=1)
group = models.ForeignKey(Group)
class Meta:
unique_together = (("boot_order", "group"))
verbose_name = "BootGroup"
verbose_name_plural = "BootGroups"
app_label = 'api_manager'
db_table = 'boot_group'
def __unicode__(self):
return "%s: %s" % (self.group.resource, self.name)
class BootGroupSerializer(ModelSerializer):
class Meta:
model = BootGroup
fields = ('name', 'boot_order', 'group')
depth = 2
class Vm(Model):
resource = models.OneToOneField(Resource, primary_key=True)
hostname = models.CharField(max_length=200, blank=True, null=True)
group = models.ForeignKey(Group, blank=True, null=True)
boot_group = models.ForeignKey(BootGroup, blank=True, null=True)
class Meta:
verbose_name = "Vm"
verbose_name_plural = "Vms"
app_label = 'api_manager'
db_table = 'vm'
def __unicode__(self):
return "%s: %s" % (self.resource.organization, self.resource)
class VmSerializer(ModelSerializer):
class Meta:
model = Vm
fields = ('resource', 'hostname', 'group', 'boot_group')
depth = 2
No matter what I try, something like "organizations/1/groups" returns all of the Group models, regardless of Organization. Am I missing something? Thanks in advance for the help.
Based on yours router definition, you need to define a queryset in GroupViewSet
from rest_framework_extensions.utils import compose_parent_pk_kwarg_name
def get_queryset(self):
resource_id = self.kwargs.get(compose_parent_pk_kwarg_name('resource_organization')
return Group.objects.filter(resource=resource_id)
The filter value can be find in kwargs as parent_lookup_<parents_query_lookups> or you can retrieve the parent query dict with self.get_parents_query_dict()

Categories

Resources