django rest framework serializers giving "serializers.Language.None" - python

Here is my serializers.py
class GetCompanySerializer(serializers.ModelSerializer):
language = serializers.CharField()
class Meta:
model = Company
fields = ('company_name','started_from','country','email','website','ip','active','language')
here is my views.py
class CompanyView(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = CompanySerializer
def get_serializer_class(self):
serializer_class = self.serializer_class
if self.request.method == 'GET':
serializer_class = GetCompanySerializer
return serializer_class
Here is my models.py
class Company(models.Model):
company_id = models.BigAutoField(primary_key=True)
company_name = models.CharField(max_length=255)
started_from = models.DateTimeField(auto_now=True)
country = models.CharField(max_length=255)
email = models.EmailField(max_length=254)
website = models.URLField()
ip = models.GenericIPAddressField(default=get_ip(),null=True,blank=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.company_name
class Language(models.Model):
language_id = models.BigAutoField(primary_key=True)
language_name = models.CharField(max_length=255)
language_logo = models.FileField()
created_on = models.DateTimeField(auto_now=True)
latest_build_on = models.DateTimeField(auto_now_add=True)
latest_version = models.DecimalField(max_digits=5, decimal_places=2)
company = models.ForeignKey('Company',on_delete=models.CASCADE,related_name='language')
def __str__(self):
return self.language_name
giving api:
[
{
"company_name": "Guido van dom rossum",
"started_from": "2018-10-03T04:58:54.889132Z",
"country": "Netherland",
"email": "help#python.com",
"website": "https://python.org",
"ip": "127.0.0.1",
"active": true,
"language": "serializers.Language.None"
}
]
it should give the language name for language field bit it is giving "serializers.Language.None" instead.
please have a look into this..

Since language is a reverse relation it shouldn't be a CharField. So you have to define a LanguageSerializer() and map it in your GetCompanySerializer as below,
class LanguageSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
model = Language
class GetCompanySerializer(serializers.ModelSerializer):
language = LanguageSerializer(many=True)
class Meta:
model = Company
fields = ('company_name', 'started_from', 'country', 'email', 'website', 'ip', 'active', 'language')
If you wish to get the __str__() reprwesentation of Language model, use StringRelatedField() instead of CharField()class GetCompanySerializer(serializers.ModelSerializer):
language = serializers.StringRelatedField(many=True)
class Meta:
model = Company
fields = ('company_name', 'started_from', 'country', 'email', 'website', 'ip', 'active', 'language')</code></pre>

Related

How to create serializer with nested data DRF?

I have seen many tutorials about nested serializer, but unfortunately I can`t solve this task. Please, give me some tips.
I need to create this JSON
{
"external_id": "11",
"details": [
{
"amount": 7,
"price": "12.00",
"product": {
"name": "Car"
}
}
]
}
My models consist the next relative:
from django.db import models
class Order(models.Model):
NEW = 'new'
ACCEPTED = 'accepted'
FAILED = 'failed'
order_status = [
(NEW, 'new'),
(ACCEPTED, 'accepted'),
(FAILED, 'failed'),
]
status = models.CharField(max_length=12, choices=order_status, default='new', blank=False)
created_at = models.DateTimeField(auto_now_add=True)
external_id = models.CharField(max_length=128)
def __str__(self):
return f'Order № {self.external_id}'
class Product(models.Model):
name = models.CharField(max_length=64)
def __str__(self):
return self.name
class OrderDetail(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE,
related_name='details',
null=True, blank=True)
amount = models.IntegerField(null=True, blank=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE,
related_name='product',
null=True)
price = models.DecimalField(decimal_places=2, max_digits=6, null=True, blank=True)
def __str__(self):
return f'Detail for {self.order}, detail for product {self.product}'
My view
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
class OrderViewSet(ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
pagination_class = ContentRangeHeaderPagination
class OrderDetailViewSet(ModelViewSet):
queryset = OrderDetail.objects.all()
serializer_class = OrderDetailSerializer
My serializer
class OrderDetailSerializer(serializers.ModelSerializer):
class Meta:
model = OrderDetail
fields = ['id', 'amount', 'price']
depth = 1
class ProductSerializer(serializers.ModelSerializer):
product = OrderDetailSerializer(many=True)
class Meta:
model = Product
fields = ['id', 'name', 'product']
class OrderSerializer(serializers.ModelSerializer):
details = OrderDetailSerializer(many=True)
class Meta:
model = Order
fields = ['id', 'status', 'created_at', 'external_id', 'details']
depth = 2
def create(self, validated_data): # works for first nesting
print(validated_data)
details_data = validated_data.pop('details')
request = Order.objects.create(**validated_data)
for detail_data in details_data: #
products_data = detail_data.pop('product')
request_detail = OrderDetail.objects.create(order=request, **detail_data)
for product_data in products_data:
Product.objects.create(product=request_detail, **product_data)
return request
I have errors when I try to send POST request. => KeyError 'products'
I wanted to get product fields using a loop. But I can't get this field, because I didn't identified it.
My question is: how to receive this field in OrderSerializer.
Thanks for your answers.

Django Foreign Key ["Incorrect type. Expected pk value, received str."]

The Company table has the basic contact information of the company, and the Address contains the address and geolocation of the company. These two tables are connected with a foreign key named "company_name," which is neither a primary key of both tables. I inserted some mock data of a company named "FF2" into the company table, it went great. However, when I attempted to insert "FF2" with its mock address into the Address table, I failed and received this:
company_name: ["Incorrect type. Expected pk value, received str."]
I tried every solution I found online, but none of them worked. Please help and be specific as possible, thank you so much!!
model.py:
class Address(models.Model):
city = models.CharField(max_length=200)
state = models.CharField(max_length=200)
zip = models.CharField(max_length=20)
address1 = models.CharField(max_length=200)
address2 = models.CharField(max_length=200, blank=True, null=True)
company_name = models.ForeignKey('Company', models.DO_NOTHING, db_column='company_name')
lat = models.DecimalField(max_digits=50, decimal_places=6)
long = models.DecimalField(max_digits=50, decimal_places=6)
class Meta:
managed = False
db_table = 'address'
class Company(models.Model):
company_name = models.CharField(unique=True, max_length=200)
contact_name = models.CharField(max_length=100)
phone = models.CharField(max_length=100)
email = models.CharField(max_length=100)
website = models.TextField()
class Meta:
managed = False
db_table = 'company'
views.py:
class AddressView(APIView):
serializer_class = AddressSerializer
def get(self, request):
address = [ {"city": address.city, "state": address.state, "zip": address.zip, "address1": address.address1, "address2": address.address2, "company_name": address.company_name, "lat": address.lat, "long": address.long}
for address in Address.objects.all()]
return Response(address)
def post(self, request):
serializer = AddressSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
class CompanyView(APIView):
serializer_class = CompanySerializer
def get(self, request):
company = [ {"company_name": company.company_name, "contact_name": company.contact_name, "phone": company.phone, "email": company.email, "website": company.website}
for company in Company.objects.all()]
return Response(company)
def post(self, request):
serializer = CompanySerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
serializer.py:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = ['city', 'state', 'zip', 'address1', 'address2', 'company_name', 'lat', 'long']
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ['company_name', 'contact_name', 'phone', 'email', 'website']

Error: expected pk value, received list for foreignkey field

I cannot save multiple values for the Foreignkey field when adding instances to the database. I don't understand exactly what the problem is: in my code or in the format of the JSON object being passed.
models.py
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'),)
serializers.py
class VendorsSerializer(serializers.ModelSerializer):
class Meta:
model = Vendors
fields = ('vendor_name',
'country',
'nda',
'parent_vendor',)
class VendorContactSerializer(serializers.ModelSerializer):
class Meta:
model = VendorContacts
fields = (
'contact_name',
'phone',
'email',)
class VendorModulSerializer(serializers.ModelSerializer):
class Meta:
model = VendorModuleNames
fields = ('module',)
views.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
serializer_class = (VendorsSerializer)
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)
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) \
vendor = vendor_serializer.save(user_id=request.user)
vendor_contact_serializer.save(vendor=vendor)
vendor_modules_serializer.save(module= maybe something here?????, vendor=vendor)
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)
JSON body
{
"vendor_name": "Awrazofgsxsdsxjwszsslsasdjegdzasas",
"country": "Canada",
"module": [
1,
2
],
"NDA date": "",
"contact_name": "Tim",
"email": "teaszt#tesstd.gmail",
"phone": "+3464784594940",
"parent_vendor": "23"
}
When I send JSON, I get the response
{
"module": [
"Incorrect type. Expected pk value, received list."
]
}
Looks like I'm finally confused about multiple saving
Your ForeignKey should be set on the related class Modules.

Django Rest Framework get a lookup field as a list of hyperlinks

I have a model Album and a model Photo, which references the first one through a FireignKey field. I want the ModelSerializer for model Album to return a list of hyperlinks to relate entries in model Photo through a lookup field, but I only get it to return a list of ids.
These are my models:
class Album(models.Model):
name = models.CharField(max_length=200, verbose_name=_("Name"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description"))
company = models.ForeignKey(Company, on_delete=models.PROTECT, related_name='albums', verbose_name=_("Company"))
access_code = models.CharField(max_length=30, default=_create_access_code, verbose_name=_("Internal Use"))
class Meta:
verbose_name = _("Album")
verbose_name_plural = _("Albums")
def __str__(self):
return "[{}] {} ({})".format(self.pk, self.name, self.company.id)
class Photo(models.Model):
name = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Name"))
album = models.ForeignKey(Album, on_delete=models.PROTECT, related_name='photos', verbose_name=_("Album"))
photo = models.ImageField(verbose_name=_("Photo"))
class Meta:
verbose_name = _("Photo")
verbose_name_plural =_("Photos")
def __str__(self):
return "[{}] {}".format(self.pk, self.name)
And this is my serializer:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
model = proxies.AlbumProxy
fields = ('id', 'name', 'description', 'company', 'access_code', 'photos')
I want the field photos to return a list of hyperlinks, but I get a list of ids:
"id": 1,
"name": "Navidad 2018",
"description": "La primera",
"company": 1,
"access_code": "xxxxxxxxxx",
"photos": [
11,
10,
7,
6
]
I think you need a HyperlinkedRelatedField, something like this:
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
model = proxies.AlbumProxy
fields = (
'id',
'name',
'description',
'company',
'access_code',
'photos'
)
photos = serializers.HyperlinkedRelatedField(
many=True,
view_name='<your-photos-view-name>',
read_only=True
)
If you want your photos full urls you can declare a Serializer Method Field to do something like this:
class AlbumSerializer(serializers.ModelSerializer):
photos_url = serializers.SerializerMethodField()
class Meta:
model = proxies.AlbumProxy
fields = ('id', 'name', 'description', 'company', 'access_code')
def get_photos_url(self, obj):
urls = []
request = self.context.get('request')
for photo in obj.photos:
urls.append(request.build_absolute_uri(photo.url))
return urls

Python Django rest-framework serializer omitting field

I'm facing a problem using python2.7 with django rest-framework. When I serialize my JSON data, a field is omitted by the serializer and I don't understand why. Here is some details.
The missing field is "country". When I'm doing POST or PUT requests on /campaigns/:id
class CampaignSerializer(serializers.HyperlinkedModelSerializer):
created_by = UserFullSerializer(read_only=True)
country = CountrySerializer(read_only=True)
class Meta:
model = Campaign
fields = ('id', 'created_by', 'name', 'media', 'status', 'begin', 'end', 'country')
class CampaignFullSerializer(serializers.HyperlinkedModelSerializer):
client = ClientSerializer(read_only=True)
collection = CollectionSerializer(read_only=True)
created_by = UserFullSerializer(read_only=True)
updated_by = UserFullSerializer(read_only=True)
channels = ChannelSerializer(read_only=True, many=True)
country = CountrySerializer(read_only=True)
class Meta:
model = Campaign
fields = ('id',
'client',
'name',
'media',
'status',
'begin',
'end',
'created_at',
'created_by',
'updated_at',
'updated_by',
'collection',
'channels',
'country')
class CountrySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Country
fields = ('id', 'name', 'code')
class Country(models.Model):
name = models.CharField(max_length=255)
code = models.CharField(max_length=255)
class Campaign(models.Model):
name = models.CharField(max_length=255)
media = models.IntegerField(choices=constant.MEDIA_CHOICES, default=0)
status = models.IntegerField(choices=constant.STATUS_CHOICES, default=2)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, blank=True, null=True, related_name="created_by")
updated_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
updated_by = models.ForeignKey(User, blank=True, null=True, related_name="updated_by")
client = models.ForeignKey(client.Client)
begin = models.DateField(blank=True, null=True)
end = models.DateField(blank=True, null=True)
collection = models.ForeignKey(collection.Collection, blank=True, null=True)
country = models.ForeignKey(country.Country, blank=True, null=True)
mediaplan = models.ForeignKey(mediaplan.Mediaplan, blank=True, null=True, default=None)
channels = models.ManyToManyField(channel.Channel)
When I'm doing POST on /campaign/id with the following JSON, everything works except the country field.
{
...
"channels": [],
"country": {
"id": 74,
"name": "France",
"code": "FR"
}
On the controller side when I print the request.data I got all the fields. I'm not overriding the create method of the controller.
{
...
u'country': {u'code': u'AL', u'id': 3, u'name': u'Albania'}
}
My controller looks like:
class CampaignViewSet(viewsets.ModelViewSet):
queryset = Campaign.objects.all()
serializer_class = CampaignSerializer
def create(self, request):
logger.info(request.data)
return super(CampaignViewSet, self).create(request, *args, **kwargs)
I tried to override the create method of my CountrySerializer and when I print the content of validated_data, the country field is missing in the OrderedDict..
class CountrySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Country
fields = ('id', 'name', 'code')
def create(self, validated_data):
logger.info(validated_data)
I'm really lost, I can't find my mistake, maybe you will. Thanks for your time.
Your CountrySerializer is read only as a nested serializer by default (per http://www.django-rest-framework.org/api-guide/relations/#nested-relationships) so you have to override the create/update method of the Campaign serializer for POST/PUT. You've tried to override it on the Country serializer instead.

Categories