DRF- how to do many readonly and writeonly fields in serializers - serialization

I used two foreignkey in my model. I want to show those fields name when we give get request I have tried but its worked only one fields not rest one.
models.py
class Organization(models.Model):
code = models.CharField(max_length=25, null=False, unique=True)
name = models.CharField(max_length=100, null=False)
location = models.ForeignKey(Location, on_delete=models.RESTRICT)
mol_number = models.CharField(max_length=100)
corporate_id = models.CharField(max_length=100)
corporate_name = models.CharField(max_length=100)
routing_code = models.CharField(max_length=100)
iban = models.CharField(max_length=100)
description = models.TextField()
total_of_visas = models.IntegerField(null=False, default=0)
base_currency = models.ForeignKey(Currency, on_delete=models.RESTRICT)
def __str__(self):
return self.name
serializers.py
class OrganizationSerializer(serializers.ModelSerializer):
location = serializers.CharField(read_only=True, source="location.name")
base_currency = serializers.CharField(read_only=True, source="base_currency.currency")
location_id = serializers.IntegerField(write_only=True, source="country.id")
base_currency_id = serializers.IntegerField(write_only=True, source="base_currency.id")
class Meta:
model = Organization
fields = ["id", "name", "location", "mol_number", "corporate_id", "corporate_name",
"routing_code", "iban", "description", "total_of_visas", "base_currency",
"location_id", "base_currency_id"]
def create(self, validated_data):
...
def update(self, instance, validated_data):
...
How can I access those two fields???.. Anyhelp Appreciable..

you can override the to_representation method
def to_representation(self, instance):
....
so something like this:
class OrganizationSerializer(serializers.ModelSerializer):
...
class Meta:
...
def to_representation(self, instance):
rep = super(OrganizationSerializer, self).to_representation(instance)
rep['location'] = instance.location.name //the .name is the field in the //location model that you want to return it can be anything in the model
rep['base_currency'] = instance.base_currency.currency
rep['location_id'] = instance.location_id.country.id
rep['base_currency_id'] = instance.base_currency_id.base_currency_id
return rep
def create(self, validated_data):
...
def update(self, instance, validated_data):

Related

drf post file to database

MODELS.PY
class MyFile(models.Model):
id = models.AutoField(primary_key=True)
in_file = models.FileField(upload_to=join_path('front/files', 'input'))
def __str__(self):
return self.in_file.name[18:]
SERIALIZERS.PY
class MyFileSerializer(serializers.ModelSerializer):
in_file = serializers.FileField(
max_length = 10000000,
allow_empty_file = False,
use_url = False,
)
class Meta:
model = MyFile
fields = ['in_file']
def create(self, validated_data):
file = validated_data.pop('in_file')
return MyFile.objects.create(in_file=file)
class DocumentChangeAPIView(APIView):
parser_classes = (FileUploadParser, FormParser)
def post(self, request):
serializer = MyFileSerializer(data=request.data)
print(request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
enter image description here
printing this response
{'file': <InMemoryUploadedFile: samandar_resume.pdf (multipart/form-data; boundary=--------------------------689093269296817855921257)>}

Get value from a Many2one related model in model create function

I have two models, TextMessage and Device, that are related many TextMessages to one Device.
from odoo import models, fields, api
class Device(models.Model):
_name = 'device'
_description = 'A model for storing all devices'
name = fields.Char()
iden = fields.Char()
model_name = fields.Char()
manufacturer = fields.Char()
push_token = fields.Char()
app_version = fields.Integer()
icon = fields.Char()
has_sms = fields.Char()
text_message_ids = fields.One2many("text_message", "device_id", string="Text Messages")
from odoo import models, fields, api
class TextMessage(models.Model):
_name = 'text_message'
_description = 'Text Messages'
name = fields.Char()
message_text = fields.Text()
pb_response = fields.Text()
target_number = fields.Char()
device_id = fields.Many2one('device', 'Device', required=True)
#api.model
#api.depends("device_id")
def create(self, values):
print("values['device_id']",values["device_id"])
print("self.device_id",self.device_id.iden)
for rec in self.device_id:
print("Device ID",rec.iden)
values['pb_response'] = rec.device_id.iden
return super().create(values)
In the create method of TextMessage, I want to retrieve the value of the iden attribute of the Device model.
The print statements in TextMessage.create print:
values['device_id'] 1
self.device_id False
The print statement in the loop prints nothing.
You can't access self before creating the record so it will be false.
You can write the create method in two ways:
Create the record first and then get the iden value:
#api.model
def create(self, values):
res = super().create(values)
res.pb_response = res.device_id.iden
return res
Or you can get the device_id record from values as below:
#api.model
def create(self, values):
if 'device_id' in values and values.get('device_id',False):
device = self.env['device'].browse(values.get('device_id'))
if device:
values['pb_response'] = device.iden
return super().create(values)
If the pb_response field is the same of the iden field then you can create it as related field to device_id.iden and you will get the iden value automatically once the device-id assigned as below:
pb_response = fields.Char(related="device_id.iden")

Django | I'd like to delete a product and all of its related data from the database

I have a shopping cart with some items in it. If I delete a product from the basket, I also want to remove it from the ordered item. I am now unable to delete the order items and quantity. I am using ajax to remove items from the cart.
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
products = models.ManyToManyField(Product, blank=True)
subtotal = models.DecimalField(default = 0.00, max_digits=100, decimal_places=2)
total = models.DecimalField(default = 0.00, max_digits=100, decimal_places=2)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = CartManager()
def __str__(self):
return str(self.id)
class OrderItem(models.Model):
Quantity_Choices =(
('one', '1'),
('Two', '2'),
('Three', '3'),
)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
quantity = models.CharField(max_length=22, choices=Quantity_Choices, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.id)
class CartManager(models.Manager):
def new_or_get(self, request):
cart_id = request.session.get("cart_id", None)
qs = self.get_queryset().filter(id=cart_id)
if qs.count() ==1:
new_obj = False
cart_obj = qs.first()
if request.user.is_authenticated and cart_obj.user is None:
cart_obj.user = request.user
cart_obj.save()
else:
cart_obj = Cart.objects.new(user=request.user)
new_obj = True
request.session['cart_id'] = cart_obj.id
return cart_obj, new_obj
def new(self, user=None):
user_obj = None
if user is not None:
if user.is_authenticated:
user_obj = user
return self.model.objects.create(user=user_obj)
The code for adding an item to the cart is as follows.
def cart_update(request):
product_id = request.POST.get('product_id')
print(product_id)
if product_id is not None:
try:
product_obj = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("No product")
return render("cart_home")
cart_obj, new_obj = Cart.objects.new_or_get(request)
if product_obj in cart_obj.products.all():
cart_obj.products.remove(product_obj)
added= False
else:
cart_obj.products.add(product_obj)
added =True
request.session['cart_items'] = cart_obj.products.count()
if request.is_ajax():
print("ajax request")
json_data = {
"added":added,
"removed": not added,
"cartItemCount":cart_obj.products.count()
}
return JsonResponse(json_data)
return redirect("cart_home")
def productdetails(request, pk):
product = Product.objects.get(id=pk)
cart, cart_created= Cart.objects.get_or_create(request)
form =sizeForm(instance=product)
if request.method =='POST':
form = sizeForm(request.POST, instance =product)
if form.is_valid():
quantity=form.cleaned_data.get('quantity')
print(quantity)
orderitem, created = OrderItem.objects.get_or_create(product=product,cart=cart, quantity=quantity)
context= {
'object' : product,
'form':form
}
return render(request, 'home/productdetails.html', context)
orderitem
cart

Convert SQL query in Django model format

I'm trying to convert an SQL query into django format but as I'm quite new to django I'm having some trouble.
My query:
select make_name, count(*) as count from main_app_make as make
join main_app_model as model on make.id = model.make_id
join main_app_vehicle as vehicle on model.id = vehicle.model_id
group by make.make_name
The result:
Audi 1
Mercedes-Benz 2
My models:
class Make(models.Model):
make_name = models.CharField(max_length=50)
make_logo = models.CharField(max_length=400)
def __str__(self):
return self.make_name
class Model(models.Model):
model_name = models.CharField(max_length=50)
make = models.ForeignKey(Make, on_delete=models.CASCADE)
def __str__(self):
return self.model_name
class Vehicle(models.Model):
type = models.ForeignKey(VehicleType, on_delete=models.CASCADE)
model = models.ForeignKey(Model, on_delete=models.CASCADE)
body_type = models.ForeignKey(Body, on_delete=models.CASCADE)
...
This is what I tried:
options = Make.objects.all().values('make_name').annotate(total=Count('make_name'))
I think you need to include the children models in the Count :
options = Make.objects.values('make_name').annotate(total=Count('model_set__vehicle_set'))
Reference : https://docs.djangoproject.com/en/stable/topics/db/aggregation/#following-relationships-backwards

How to solve TypeError: Object of type 'Category' is not JSON serializable

I have 3 tables (Book,Author,Category)
when I try to get a list of books or authors I have this error: TypeError: Object of type 'Category' is not JSON serializable. I think it's related to the relationship with the category table. Could you please check my models is it structure well or not and how can I solve this issue.
__tablename__ = 'author'
id = db.Column(db.Integer().with_variant(Integer, "sqlite"), primary_key=True)
auth_nam = db.Column(db.String, nullable=False)
gender = db.Column(db.String, nullable=True)
count_book = db.Column(db.Integer,nullable=False)
category=db.relationship('Category', backref='author', lazy=True)
def __init__(self,auth_nam,gender,count_book,category):
self.auth_nam = auth_nam
self.gender = gender
self.count_book = count_book
self.category = category
def insert(self):
db.session.add(self)
db.session.commit()
def update(self):
db.session.commit()
def delete(self):
db.session.delete(self)
db.session.commit()
def format(self):
return {
'id': self.id,
'auth_nam': self.auth_nam,
'gender': self.gender,
'count_book': self.count_book,
'category': self.category
}
'''
Books
'''
class Book(db.Model):
__tablename__='book'
id = db.Column(db.Integer().with_variant(Integer, "sqlite"), primary_key=True)
book_name=db.Column(db.String,nullable=False)
book_issue=db.Column(db.DateTime,nullable=False)
category=db.relationship('Category', backref='book', lazy=True)
def __init__(self, book_name, book_issue, category):
db.create_all()
self.book_name = book_name
self.book_issue = book_issue
self.category = category
def insert(self):
db.session.add(self)
db.session.commit()
def update(self):
db.session.commit()
def delete(self):
db.session.delete(self)
db.session.commit()
def format(self):
return {
'id': self.id,
'book_name': self.book_name,
'book_issue': self.book_issue,
'category': self.category,
}
'''
Category
'''
class Category(db.Model):
__tablename__ = 'category'
id = Column(db.Integer, primary_key=True)
name = Column(db.String,nullable=False)
book_id = db.Column(db.Integer, db.ForeignKey('book.id'),nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'),nullable=False)
def __init__(self, name, book_id, author_id):
self.name = name
self.book_id = book_id
self.author_id = author_id
def insert(self):
db.session.add(self)
db.session.commit()
def update(self):
db.session.commit()
def delete(self):
db.session.delete(self)
db.session.commit()
def format(self):
return {
'id': self.id,
'name': self.name,
'book_id': self.book_id,
'author_id': self.author_id,
}
def format(self):
return {
'id': self.id,
'book_name': self.book_name,
'book_issue': self.book_issue,
'category': self.category,
}
'''
Category
'''
class Category(db.Model):
__tablename__ = 'category'
id = Column(db.Integer, primary_key=True)
name = Column(db.String,nullable=False)
book_id = db.Column(db.Integer, db.ForeignKey('book.id'),nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'),nullable=False)
def __init__(self, name, book_id, author_id):
self.name = name
self.book_id = book_id
self.author_id = author_id
def insert(self):
db.session.add(self)
db.session.commit()
def update(self):
db.session.commit()
def delete(self):
db.session.delete(self)
db.session.commit()
def format(self):
return {
'id': self.id,
'name': self.name,
'book_id': self.book_id,
'author_id': self.author_id,
}
app.py:
#app.route('/books', methods=['GET'])
def get_books():
books = Book.query.all()
books_formated=[book.format() for book in books]
return jsonify({
"success": True,
"books":books_formated
})
Since you have set the category as a relationship attribute on Book model, when you call this line in your Book.format():
'category': self.category
the self.category will return the related Category instance, it's a Python object. However, the Python object is not JSON serializable, that's why you got TypeError: Object of type 'Category' is not JSON serializable. when jsonify() was called.
To solve this, you can either change self.category to 'category': [category.name for category in self.category] (get the string of the category name) or 'category': [category.format() for category in self.category] (get the dict of the category data). Both string and dict are JSON serializable.