How to check if a record already exists or not in database in DRF? - orm

I am working on DRF. I am creating an API of POST request that overriding its features. I want to add one functionality if a particular field value already exists in DB then, user cannot create post request and instead of it getting a message that he couldn't do it.
views.py
class PizzaOrderViewSet(viewsets.ModelViewSet):
http_method_names = ['get', 'put', 'patch', 'post']
def create(self, request, *args, **kwargs):
data = request.data
order = PizzaOrder.objects.create(
name=data['name'], flavours=data['flavours'],
number=data['number'], size=data['size'],
customer_name=data['customer_name'],
customer_address=data['customer_address']
)
order.save()
serializer = PizzaOrderSerializer(order)
return Response(serializer.data)
serializers.py
class PizzaOrderSerializer(serializers.ModelSerializer):
class Meta:
model = PizzaOrder
validators = [
UniqueTogetherValidator(
queryset=PizzaOrder.objects.all(),
fields=['name', 'flavours', 'size', 'customer_name', 'customer_address'],
message='This field should be unique'
)
]
models.py
from django.db import models
from datetime import datetime
FLAVOURS_CHOICE = (
('Margarita', 'Margarita'),
('Marinara', 'Marinara'),
('Salami', 'Salami'),
)
SIZE_CHOICE = (
('Small', 'Small'),
('Medium', 'Medium'),
('Large', 'Large'),
)
STATUS_CHOICE = (
('Open', 'Open'),
('Accepted', 'Accepted'),
('Preparing', 'Preparing'),
('OnWay', 'OnWay'),
('Delivered', 'Delivered'),
)
class PizzaOrder(models.Model):
name = models.CharField(max_length=50, blank=False)
flavours = models.CharField(max_length=20, choices=FLAVOURS_CHOICE)
quantity = models.IntegerField()
size = models.CharField(max_length=10, choices=SIZE_CHOICE)
customer_name = models.CharField(max_length=30, blank=False)
customer_address = models.TextField(blank=False)
ordered_time = models.DateTimeField(default=datetime.now, editable=False)
status = models.CharField(max_length=20, choices=STATUS_CHOICE, default='Open')
def __str__(self):
return self.name
class Meta:
ordering = ['-ordered_time']
unique_together = ('name', 'flavours', 'quantity', 'size')
How could I achieve this?

Related

Update records on one2many fields in wizard for odoo16

Geting Issue 'TypeError: unhashable type: 'dict' for insert values in one2many field from onchange method in odoo16
My code is below:
class EmployeeAddWizard(models.TransientModel):
_name = 'employee.add.wizard'
line_ids = fields.One2many('employee.goal.add.line', 'wizard_id', string="Lines")
#api.onchange('challenge_id', 'employee_id')
def _onchange_action_goal_add(self):
r = []
value = {}
self.line_ids = {}
if self.challenge_id and self.employee_id:
goal_records = self.env['gamification.challenge.line'].search([('challenge_id', '=', self.challenge_id.id)])
for emp in self.employee_id:
for line in goal_records:
data = {'wizard_id': self.id, # Other table m2o
'goal_definition_id': line.definition_id.id,
'goal_rating': 0.0,
'goal_target': line.target_goal,
'employee_id': emp.id,
}
r.append(data)
value.update(records=r)
self.line_ids = value['records']
class GoalLine(models.Model):
_name = 'employee.goal.add.line'
wizard_id = fields.Integer()
goal_definition_id = fields.Many2one('gamification.goal.definition', string='Goal Definition', required=True, ondelete="cascade")
goal_rating = fields.Float('Rating', required=True)
goal_target = fields.Float('Target Value ', required=True)
employee_id = fields.Many2one('res.users', string="Employee", required=True, ondelete="cascade")
Thanks in advance
You passed a list of dicts which is not valid, you need to use special commands
Example:
r.append(Command.create(data))
or:
r.append((0, 0, data))
You can use Command.clear(), to remove previous lines if needed ( self.line_ids = {} should raise an error: ValueError: Wrong value).
Check this answer

Django Rest Framework getting Bad Request:400 error with serializer errors that I thought I took care of but I can't figure out where I went wrong?

I am trying to make a post request through insomnia to create a snake instance, but I am getting a Bad Request:400 error. I printed the serializer errors and got this:
{
'owner': [ErrorDetail(string='Incorrect type. Expected URL string, received ReturnDict.', code='incorrect_type')],
'birthday': [ErrorDetail(string='This field is required.', code='required')],
'date_aquired': [ErrorDetail(string='This field is required.', code='required')],
'species': [ErrorDetail(string='Incorrect type. Expected URL string, received ReturnDict.', code='incorrect_type')],
'breeder_id': [ErrorDetail(string='This field is required.', code='required')],
'mother': [ErrorDetail(string='This field is required.', code='required')],
'father': [ErrorDetail(string='This field is required.', code='required')]
}
Here is my serializer which I thought would take care of the null/blank fields:
class SnakeDetailSerializer(serializers.HyperlinkedModelSerializer):
href = serializers.HyperlinkedIdentityField(view_name="api_species_detail")
birthday = serializers.DateField(allow_null=True)
date_aquired = serializers.DateField(allow_null=True)
enclosure_id = serializers.CharField(allow_null=True, allow_blank=True)
breeder_id = serializers.CharField(allow_null=True, allow_blank=True)
father = serializers.CharField(allow_null=True, allow_blank=True)
mother = serializers.CharField(allow_null=True, allow_blank=True)
class Meta:
model = Snake
fields = [
'href',
'id',
'owner',
'name',
'age',
'birthday',
'date_aquired',
'gender',
'status',
'weight',
'enclosure_id',
'species',
'is_cbb',
'is_imported',
'breeder_id',
'mother',
'father'
]
Here is my model:
class Snake(models.Model):
# BASIC INFO
owner = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name="collection",
on_delete=models.CASCADE
)
STATUS_CHOICES = (
('Active', 'Active'),
('Deceased', 'Deceased'),
('Quarantine', 'Quarantine'),
('For Sale', 'For Sale'),
('On Loan', 'On Loan'),
('Reserved', 'Reserved'),
('Sold', 'Sold')
)
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
('NA', 'Unknown')
)
name = models.CharField(max_length=255)
age = models.SmallIntegerField()
birthday = models.DateField(null=True, blank=True)
date_aquired = models.DateField(null=True, blank=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES)
gender = models.CharField(max_length=2, choices=GENDER_CHOICES)
weight = models.DecimalField(max_digits=10, decimal_places=2)
enclosure_id = models.CharField(max_length=255, null=True, blank=True)
# SPECIES INFO
species = models.ForeignKey(SpeciesInfo, related_name="snakes", on_delete=models.PROTECT)
# LINEAGE INFO
is_cbb = models.BooleanField(default=False)
is_imported = models.BooleanField(default=False)
breeder_id = models.CharField(max_length=255, null=True, blank=True)
mother = models.CharField(max_length=255, null=True, blank=True)
father = models.CharField(max_length=255, null=True, blank=True)
here is my view:
#api_view(['GET', 'POST'])
def api_list_snakes(request):
if request.method == 'GET':
snakes = Snake.objects.all()
serializer = SnakeListSerializer(snakes, many=True)
return Response(
{'snakes': serializer.data}
)
else:
data = JSONParser().parse(request)
# print(data)
species = SpeciesInfo.objects.get(id=data["species"])
species_serialized = SpeciesInfoSerializer(species, context={'request':request})
owner = GetUserSerializer(request.user)
data['owner'] = owner.data
data["species"] = species_serialized.data
serializer = SnakeDetailSerializer(data=data, context={'request':request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
print(serializer.errors)
return Response(serializer.data, status=400)
I have also added a photo of the insomnia request.insomnia_request
I thought adding the allow_null and allow_blank on the fields would correct the bad request error but it doesn't seem to have changed anything I am also getting errors for my foreign key fields and I am not sure why?
Help would be very much appreciated! Thanks!
I tried to add the fields that were allowed to be blank/null to the serializer here:
class SnakeDetailSerializer(serializers.HyperlinkedModelSerializer):
href = serializers.HyperlinkedIdentityField(view_name="api_species_detail")
birthday = serializers.DateField(allow_null=True)
date_aquired = serializers.DateField(allow_null=True)
enclosure_id = serializers.CharField(allow_null=True, allow_blank=True)
breeder_id = serializers.CharField(allow_null=True, allow_blank=True)
father = serializers.CharField(allow_null=True, allow_blank=True)
mother = serializers.CharField(allow_null=True, allow_blank=True)
and I expected that to correct the errors saying that they were required fields but they did not.
I also thought I had corrected the Foreign Key issues but it says they are expected a url string? I was using the id and it is getting the correct one so I'm not sure why it is mad about it
I figured out how to fix my required field error. I had to add required=True to the serializer fields but I still can't get the foreign keys to work

Django restframework SerializerMethodField background work

I am writing a project in Django with rest framework by using SerializerMethodField. This method makes queries for every row to get data, or View collects all queries and send it to DB? Django can make it as one joint query?
class SubjectSerializer(serializers.ModelSerializer):
edu_plan = serializers.SerializerMethodField(read_only=True)
academic_year_semestr = serializers.SerializerMethodField(read_only=True)
edu_form = serializers.SerializerMethodField(read_only=True)
def get_edu_plan(self, cse):
return cse.curriculum_subject.curriculum.edu_plan.name
def get_academic_year_semestr(self, cse):
semester = cse.curriculum_subject.curriculum.semester
return {'academic_year': semester.academic_year, 'semester': semester}
def get_edu_form(self, cse):
return cse.curriculum_subject.curriculum.edu_form.name
class Meta:
model = CurriculumSubjectEmployee
fields = [
'id',
'name',
'edu_plan',
'academic_year_semestr',
'edu_form'
]
class SubjectViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = SubjectSerializer
def get_queryset(self):
contract = self.request.user.employee.contract
if contract is None:
raise NotFound(detail="Contract not found", code=404)
department = contract.department
cses = CurriculumSubjectEmployee\
.objects\
.filter(curriculum_subject__department=department)
return cses

How to track One2many field in Odoo12?

I am trying to log the changes on a One2many field using track_visibility='onchange'. But it's not working.
Here is the code:
respartner.py
bank_account_ids = fields.One2many('customer.bank.account','partner_id',
string='Account',track_visibility="onchange")
account.py
_name = 'customer.bank.account'
_description = 'Partner Bank Account Details'
partner_id = fields.Many2one('res.partner',string="Partner")
name = fields.Integer(string="Account Number",required=True,
track_visibility="onchange")
bank_id = fields.Many2one('partner.bank',string="Bank",track_visibility="onchange")
branch_id = fields.Many2one('partner.bank.branch',string="Branch",
track_visibility="onchange")
Yes, No need to touch ORM. Try this
class ParentClass(models.Model):
_name = 'parent.class'
_inherit = ['mail.thread']
child_ids = fields.One2many('child.class', 'relational_field_name_id')
class ChildClass(models.Model):
_name = 'child.class'
_inherit = ['mail.thread']
name = fields.Char(tracking=True) # Note that tracking is true here
relational_field_name_id = fields.Many2one('parent.class')
def write(self, vals):
super().write(vals)
if set(vals) & set(self._get_tracked_fields()):
self._track_changes(self.relational_field_name_id)
def _track_changes(self, field_to_track):
if self.message_ids:
message_id = field_to_track.message_post(body=f'<strong>{ self._description }:</strong> { self.display_name }').id
trackings = self.env['mail.tracking.value'].sudo().search([('mail_message_id', '=', self.message_ids[0].id)])
for tracking in trackings:
tracking.copy({'mail_message_id': message_id})
If you just want to track on relational and not current model then use write instead of copy method
tracking.write({'mail_message_id': message_id})
And for delete and create you can just use message_post inside create and unlink method
self.message_post(body=f'<strong>{ self._description }:</strong> { self.display_name } created/deleted')

About the onchange method returning domain or warning in odoo8

I tried following the odoo8 official example,but not works for me:
class TestMove(models.Model):
_name = 'test.move'
_description = 'Stock Requisition Return'
num1 = fields.Float(string='num1')
num_float = fields.Float(string='num_float', compute="_compute_num_float", store=True)
num2 = fields.Integer(string='num2')
age = fields.Integer(compute='_compute_age')
age2 =fields.Integer(compute='_compute_age2', store=True)
now_list_price = fields.Float(
string='Now List Price', help='Now List Price', digits=(10, 10))
product_id = fields.Many2one(comodel_name='product.product')
......
#api.one
#api.onchange('num1')
def _onchange_num2(self):
now_ = self.num1 + 1
_logger.info('num2 is:%s', now_)
self.update({'num2': now_})
return {
'domain': {'product_id': [('id', 'in', [now_])]},
'warning': {'title': "Warning", 'message': "What is this?"}
}
class ProductProduct(models.Model):
_name = 'product.product'
_description = 'Product'
_rec_name = 'name'
name = fields.Char()
price_unit = fields.Float(default=Decimal('13.14'))
num2 has changed, but domain and warning are not returned;
Any suggestion please. Thanks in advance.
The issue is caused by #api.one decorator, just remove it and the onchange method should work correctly.