I have 3 model Product - Peyment - ProductDiscountControll
Peyment and ProductDiscountControll have relation to column "product" to Product table
I want to have related ProductDiscountControll data like discount and discount_code_precent in peyment serilizer at get request.
In quest to do that, I tried following code in my Serializer Class
def get_product_discount(self, obj):
return obj.product.product_discount.discount
but server says :
Field name `product_discount` is not valid for model `Peyment`.
I also tried like this way:
product_discount = ProductDiscountControllSerializer(many=True,read_only=True)
but product_discount not available in result
my view is look like this
class PeymentAPIView(APIView, mixins.DestroyModelMixin):
permission_classes = [IsSafeGuard]
def get(self, request):
pay = Peyment.objects.filter(
email=request.user.email,
status=0,
)
serializer = PeymentSerializer(instance=pay, many=True)
return Response(serializer.data)
this is related Serializer class for get request:
class PeymentSerializer(ModelSerializer):
producttitle = serializers.SerializerMethodField()
def get_producttitle(self, obj):
return obj.product.title
productprice = serializers.SerializerMethodField()
def get_productprice(self, obj):
return obj.product.price
def get_discount(self, obj):
return obj.product_discount.discount
#product_discount = ProductDiscountControllSerializer(many=True,read_only=True)
class Meta:
model = Peyment
fields = [
'product',
'id',
'producttitle',
'productprice',
'discount',
'status',
'user',
'email',
'transfer_id',
'created_date',
'updated_date',
]
read_only_fields = ['email', 'user', 'producttitle', 'productprice']
this is Product model:
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)
title = models.CharField(max_length=200)
video_length = models.CharField(max_length=20, null=True, blank=True)
mini_description = models.CharField(max_length=1000, null=True, blank=True)
full_description = models.TextField(null=True, blank=True)
you_need = models.CharField(max_length=1000, null=True)
you_learn = models.CharField(max_length=2000, null=True)
price = models.CharField(max_length=50, null=True, blank=True)
video_level = models.CharField(max_length=100, null=True, blank=True)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
image = models.FileField(upload_to=upload_to_custom_p,null=True,blank=True)
Peyment model:
class Peyment(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, to_field='product_id',
related_name='product_peyment')
status = models.CharField(max_length=30, null=True)
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
transfer_id = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField()
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
and discount model:
class ProductDiscountControll(models.Model):
product = models.OneToOneField(Product, on_delete=models.CASCADE, to_field='product_id',
related_name='product_discount')
discount = models.IntegerField(max_length=50, null=True, blank=True)
discount_code = models.CharField(max_length=50, null=True, blank=True)
discount_code_precent = models.CharField(max_length=80, null=True, blank=True)
updated_date = models.DateTimeField(auto_now=True)
updated :
# product peyment
class PeymentSerializer(ModelSerializer):
producttitle = serializers.SerializerMethodField()
def get_producttitle(self, obj):
return obj.product.title
productprice = serializers.SerializerMethodField()
def get_productprice(self, obj):
return obj.product.price
def get_discount(self, obj):
serializer = ProductDiscountControllSerializer(obj.product.product_discount)
return serializer.data
class Meta:
model = Peyment
fields = [
'product',
'id',
'producttitle',
'productprice',
'discount',
'status',
'user',
'email',
'transfer_id',
'created_date',
'updated_date',
]
read_only_fields = ['email', 'user', 'producttitle', 'productprice']
You can just use product.product_discount field name in serializer's method. To return serialized data you should pass this value to ProductDiscountControllSerializer and return serializer.data:
def get_discount(self, obj):
discount = getattr(obj.product, 'product_discount', None)
if discount:
serializer = ProductDiscountControllSerializer(discount)
return serializer.data
return None
UPD
You should explicitly declare discount field in serializer with SerializerMethodField to use it in fileds list:
class PeymentSerializer(ModelSerializer):
discount = serializers.SerializerMethodField()
Related
This is my code for the hotel website
models.py
class Rooms(models.Model):
room = models.BigIntegerField(verbose_name='Комната', unique=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='Категория', related_name='wer')
room_bool = models.BooleanField(verbose_name='Статус', default=True)
price = models.BigIntegerField(verbose_name='Цена', null=True,blank=True)
class Registrations(models.Model):
room_num = models.ForeignKey(Rooms, on_delete=models.CASCADE, verbose_name='Номер', related_name='ertgdb',
limit_choices_to={'room_bool': True})
first_name = models.CharField(max_length=250, verbose_name='Имя')
last_name = models.CharField(max_length=250, verbose_name='Фамилия')
tel_num = models.BigIntegerField(verbose_name='Номер телефона')
img = models.FileField(verbose_name='Паспорт', null=True, blank=True)
visit_date = models.DateField(default=now, verbose_name='Дата прибытия')
leave_date = models.DateField(blank=True, null=True, help_text='Дата отбытия')
guest_count = models.IntegerField(default=1, verbose_name='Кол-во людей')
room_relevant = models.BooleanField(default=False, verbose_name='Статус')
price = models.BigIntegerField(verbose_name='Цена', default=100)
serializers.py
class RegistrationSer(serializers.ModelSerializer):
class Meta:
model = Registrations
fields = ('id', 'room_num', 'first_name', 'last_name', 'tel_num', 'img',
'visit_date', 'guest_count', 'room_relevant')
I need the room_num field (in the picture) to have not Id but room_num as in the Input form
SlugRelatedField doesn't work because I can't make POST PUT requests later
You can do the following:
class RegistrationSer(serializers.ModelSerializer):
room = serializers.CharField(source="room_num.room")
class Meta:
model = Registrations
fields = ('id', 'room', 'first_name', 'last_name', 'tel_num', 'img',
'visit_date', 'guest_count', 'room_relevant')
So the user can take some quiz and earn xp only at first try. From the second try on I only want to calculate how many correct answer scored but not xp will be earn.
My models:
class ClassAttempt(models.Model):
user = models.ForeignKey(to=User,on_delete= models.PROTECT, null=True)
related_class = models.ForeignKey(to=Class, related_name='attempt', on_delete= models.PROTECT, null=True)
collected_xp = models.IntegerField(null=True, blank=True, default=0)
status = models.CharField(
verbose_name='status',
max_length=20,
choices=(
('no-completed', 'no-completed'),
('completed', 'completed'),
),
default='no-completed'
)
try_num = models.IntegerField(null=True, blank=True, default=1)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class UserClassQuestionsRecord(models.Model):
user = models.ForeignKey(to=User, related_name='user_class_question_record', on_delete=models.CASCADE, null=True)
question = models.ForeignKey(to=ClassQuiz, related_name='question_selected', on_delete=models.PROTECT, null=True, blank=True)
selected_answer = models.ForeignKey(to=QuizAnsClass, related_name='answer_selected', on_delete=models.PROTECT, null=True, blank=True)
is_correct = models.CharField(
verbose_name='status',
max_length=10,
choices=(
('True', 'True'),
('False', 'False'),
),
default=''
)
try_num = models.IntegerField(null=True, blank=True, default=1)
xp_collected = models.IntegerField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
My View:
class UserClassScore(ListAPIView):
"""
Get User Score at the end of each class by Class ID
Get request
"""
queryset = ClassAttempt.objects.all()
serializer_class = UserClassScoreSerializer
permission_classes = [IsAuthenticated]
lookup_field = 'id'
def get_queryset(self):
queryset = self.queryset.filter(related_class_id=self.kwargs.get('id'), try_num=1)
if not queryset:
self.serializer_class = UserClassScoreSerializerNoXp
return queryset
else:
self.serializer_class = UserClassScoreSerializer
return queryset
My serializers :
class UserClassScoreSerializer(serializers.ModelSerializer):
score = serializers.SerializerMethodField()
xp_collected = serializers.SerializerMethodField()
def get_score(self, obj):
class_data = UserClassQuestionsRecord.objects.filter(user=self.context['request'].user,
question__singleclass_id=obj.related_class.id,
try_num=1,
is_correct='True').all()
return class_data.__len__()
def get_xp_collected(self, obj):
class_data = UserClassQuestionsRecord.objects.filter(user=self.context['request'].user,
question__singleclass_id=obj.related_class.id,
try_num=1,
is_correct='True').all()
obj_count = class_data.__len__()
return obj_count * 10
class Meta:
model = Class
fields = ['score', 'xp_collected']
class UserClassScoreSerializerNoXp(serializers.ModelSerializer):
score = serializers.SerializerMethodField()
xp_collected = serializers.SerializerMethodField()
def get_score(self, obj):
class_data = UserClassQuestionsRecord.objects.filter(user=self.context['request'].user,
question__singleclass_id=obj.related_class.id,
**try_num=2,**
is_correct='True').all()
return class_data.__len__()
def get_xp_collected(self, obj):
return 0
class Meta:
model = Class
fields = ['score', 'xp_collected']
So try_num is how I'm tracking on which attempt it is. The thing is that the user can take more that 2 attempts let's say to infinitive attempts.
You can get the first object in table using first()
MyModel.objects.first()
so calculate the xp from this result
or
MyModel.objects.all()[:number_for_question_you_want]
example:
MyModel.objects.all()[:5]
also you can use .values() or any other filter you want
I want special users (vendors) to see their own orders in their django admin. When ever I tried that it filters out the user that ordered the products. Here are the codes.
I connected the vendors in my product model. I can't figure out how to connect vendors with their respective orders.
class Order(models.Model):
STATUS = (
('New', 'New'),
('Accepted', 'Accepted'),
('Preparing', 'Preparing'),
('OnShipping', 'OnShipping'),
('Completed', 'Completed'),
('Canceled', 'Canceled'),
)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
code = models.CharField(max_length=5, editable=False)
first_name = models.CharField(max_length=10)
last_name = models.CharField(max_length=10)
phone = models.CharField(blank=True, max_length=20)
address = models.CharField(blank=True, max_length=150)
city = models.CharField(blank=True, max_length=20)
country = models.CharField(blank=True, max_length=20)
total = models.FloatField()
status=models.CharField(max_length=10,choices=STATUS,default='New')
ip = models.CharField(blank=True, max_length=20)
adminnote = models.CharField(blank=True, max_length=100)
create_at=models.DateTimeField(auto_now_add=True)
update_at=models.DateTimeField(auto_now=True)
class OrderProduct(models.Model):
STATUS = (
('New', 'New'),
('Accepted', 'Accepted'),
('Canceled', 'Canceled'),
)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
variant = models.ForeignKey(Variants, on_delete=models.SET_NULL,blank=True, null=True) # relation with variant
quantity = models.IntegerField()
price = models.FloatField()
amount = models.FloatField()
status = models.CharField(max_length=10, choices=STATUS, default='New')
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.product.title
class OrderAdmin(admin.ModelAdmin):
list_display = ['first_name', 'last_name','phone','city','total','status','create_at']
list_filter = ['status']
readonly_fields = ('user','address','city','country','phone','first_name','ip', 'last_name','phone','city','total')
can_delete = False
inlines = [OrderProductline]
class OrderProductAdmin(admin.ModelAdmin):
list_display = ['user', 'product','price','quantity','amount']
list_filter = ['product']
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(product=request.product)```
Change your ModelAdmin subclass:
class OrderProductAdmin(admin.ModelAdmin):
list_display = ['user', 'product','price','quantity','amount']
list_filter = ['product']
def get_queryset(self, request):
return super().get_queryset(request).filter(product__user=request.user)
I have a django app with following sections
models:
class Report(models.Model):
created_by_user=models.ForeignKey(User,on_delete=models.CASCADE)
planet_name = models.CharField(max_length=100)
outage_id = models.IntegerField(blank=True, default=0)
unit_name = models.CharField(max_length=10, blank=True, null=True)
responsible_group = models.CharField(max_length=50, blank=True)
alarm_num = models.IntegerField(blank=True, default=0)
raised_alarm = models.CharField(max_length=255, blank=True)
start_time = models.DateTimeField(blank=True)
end_time = models.DateTimeField(blank=True)
event_desc = models.TextField(max_length=5000, blank=True)
power_changes = models.FloatField(blank=True)
rel_asset = models.CharField(max_length=255, blank=True)
event_cause = models.TextField(max_length=1000, blank=True)
maintenance_action = models.TextField(max_length=1000, blank=True)
maintenance_cost = models.IntegerField(blank=True)
maintenance_mh = models.IntegerField(blank=True)
maintenance_dc = models.TextField(max_length=5000, blank=True)
serializer:
class ReportSerializer(serializers.ModelSerializer):
created_by_user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model=Report
fields='__all__'
view:
class ReportCreateView(APIView):
def post(self,request, *args, **kwargs):
received_data=ReportSerializer(data=request.data, context = {"request": request})
if received_data.is_valid():
received_data.save()
return Response(received_data.data, status=status.HTTP_201_CREATED)
return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)
but when I send a report by Post method this error rise:
(1048, "Column 'start_time' cannot be null")
How I can fix it?I set blank=True for all fields but why it raise errors?
I'm getting a duplicate code in query, how can i merge 2 variable into 1 line
def destroy(self, request, pk=None):
date_time = datetime.now()
user = get_object_or_404(User, pk=request.user.id)
transaction = TransactionVariant.objects.filter(transaction__pk=pk).update(deleted_at=date_time)
transaction = Transaction.objects.filter(id=pk).update(deleted_at=date_time)
serializer = TransactionSerializer(transaction, many=True)
return Response(serializer.data, many=True)
my model:
transaction.py
class Transaction(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
address = models.TextField()
status = models.CharField(max_length=100)
total = models.BigIntegerField()
phone_number = models.CharField(max_length=10)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True)
deleted_at = models.DateTimeField(null=True, blank=True)
class Meta:
db_table = "transaction"
transaction_variant.py
class TransactionVariant(models.Model):
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
variant = models.ForeignKey(Variant, on_delete=models.CASCADE)
quantity = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True)
deleted_at = models.DateTimeField(null=True, blank=True)
class Meta:
db_table = "transaction_variant"