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
Related
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 want that in my project the members who are having role as manager should not be able to see the priority field while updating the form
models.py
class Ticket(models.Model):
status_choice = (
("Approval", "Approval"),
("Assigned", "Assigned"),
("Scoping", "Scoping"),
("In Progress", "In Progress"),
("Completed", "Completed"),
("Cancelled", "Cancelled"),
("Rejected", "Rejected"),
)
priority_choice = (
("High", "High"),
("Moderate", "Moderate"),
("Low", "Low"),
)
category = models.ForeignKey("vats.Category", on_delete=models.CASCADE)
subcategory = models.ForeignKey("vats.Subcategory", on_delete=models.CASCADE)
title = models.CharField(
_("Title"),
max_length=50,
)
problem_descp = models.TextField(_("Problem Description"), max_length=500)
created_by = models.ForeignKey("registration.User", related_name=_("Issues"), on_delete=models.CASCADE)
priority = models.CharField(_("Priority"), max_length=50, null=True, blank=True, choices=priority_choice)
start_date_time = models.DateTimeField(_("Start Date Time"), auto_now_add=True)
end_date_time = models.DateTimeField(_("End Date Time"), null=True, blank=True)
assigned_to = models.ForeignKey("registration.User", related_name=_("Tasks"), on_delete=models.SET_NULL, null=True, blank=True)
status = models.CharField(_("Status"), max_length=50, choices=status_choice, null=True, blank=True)
class Meta:
verbose_name = _("Ticket")
verbose_name_plural = _("Tickets")
def __str__(self):
return self.title
def is_open(self):
if self.status == "Completed" or self.status == "Cancelled":
return False
return True
forms.py
class TicketForm(forms.ModelForm):
# subcategory = forms.ModelChoiceField(queryset=Subcategory.objects.filter(category__id = self.fields['category']))
class Meta:
model = Ticket
fields = ("category", "subcategory", "title", "problem_descp")
class TicketUpdateForm(forms.ModelForm):
class Meta:
model = Ticket
fields = ("category", "subcategory", "title", "problem_descp", "status", "assigned_to", "priority")
def __init__(self, *args, **kwargs):
super(TicketUpdateForm, self).__init__(*args, **kwargs)
self.fields["category"].disabled = True
self.fields["subcategory"].disabled = True
self.fields["title"].disabled = True
self.fields["problem_descp"].disabled = True
Error message AttributeError: 'NoneType' object has no attribute 'add'
am trying to create an instance of a model.
the card model is suppose to be an instance of the patient model and the patient model has a foreign key relations with the user model.
Its like a patient who has a card in the hospital.
My error is coming from the perform_create method
views.py
class PatientCardListAPIView(ListCreateAPIView):
serializer_class = PatientsCardSerializer
queryset = Card.objects.all()
permission_classes = (permissions.IsAuthenticated, IsOwner, )
def perform_create(self, serializer):
serializer.save()
serializer.instance.owner.add(self.request.user)
models.py
from django.db import models
from authentication.models import User
# Create your models here.
class Patient(models.Model):
name = models.CharField(max_length=255, null=True)
country = models.CharField(max_length=255, null=True)
state = models.CharField(max_length=255, null=True)
phone = models.CharField(max_length=255, null=True)
email = models.CharField(max_length=255, null=True)
owner = models.ForeignKey(to=User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Card(models.Model):
name = models.CharField(max_length=255, null=True)
card_number = models.CharField(max_length=255, null=True)
owner = models.OneToOneField(Patient, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
It should be as
class PatientCardListAPIView(ListCreateAPIView):
serializer_class = PatientsCardSerializer
queryset = Card.objects.all()
permission_classes = (permissions.IsAuthenticated, IsOwner,)
def perform_create(self, serializer):
serializer.save(owner = self.request.user)
This should be:
def perform_create(self, serializer):
model_instance = serializer.save(owner=self.request.user)
OR
def perform_create(self, serializer):
model_instance = serializer.save()
model_instance.owner = self.request.user
Edited
..............
A closer look at your model shows that you need to redefine the model. As you've defined, the owner field under Patient class indicated that you can have a User who can be many Patient...(a query of: patient=Patient.objects.get(owner=self.request.user) may return more than one instance. ). Suggested model should be:
class Patient(models.Model):
name = models.CharField(max_length=255, null=True)
country = models.CharField(max_length=255, null=True)
state = models.CharField(max_length=255, null=True)
phone = models.CharField(max_length=255, null=True)
email = models.CharField(max_length=255, null=True)
**owner = models.OneToOneField(User, null=True)**
def __str__(self):
return self.name
class Card(models.Model):
name = models.CharField(max_length=255, null=True)
card_number = models.CharField(max_length=255, null=True)
owner = models.OneToOneField(Patient, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
Then you can have your view:
class PatientCardListAPIView(ListCreateAPIView):
serializer_class = PatientsCardSerializer
queryset = Card.objects.all()
permission_classes = (permissions.IsAuthenticated, IsOwner, )
def perform_create(self, serializer):
card_instance = serializer.save()
patient = Patient.objects.get(owner=self.request.user)
card_instance.owner = patient
Appreciation
I was almost discouraged with programming for the past 24hrs because of this problem, but this community helped me, even though they did not give the answer i needed, they led me into discovering the answer myself, and i say Thank you to stackoverflow community...
Solved
I finally discovered what i was doing wrong.
a card does not just belong to a patient, it also belongs to a hospital, so the card needs a relation to both the hospital and the patient.
models.py
class Patient(models.Model):
name = models.CharField(max_length=255, null=True)
country = models.CharField(max_length=255, null=True)
state = models.CharField(max_length=255, null=True)
phone = models.CharField(max_length=255, null=True)
email = models.CharField(max_length=255, null=True)
owner = models.ForeignKey(to=User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Card(models.Model):
name = models.CharField(max_length=255, null=True)
card_number = models.CharField(max_length=255, null=True)
owner = models.OneToOneField(Patient, null=True, blank=True, on_delete=models.CASCADE)
hospital = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
views.py
class PatientCardListAPIView(ListCreateAPIView):
serializer_class = PatientsCardSerializer
queryset = Card.objects.all()
permission_classes = (permissions.IsAuthenticated, IsOwner, )
def perform_create(self, serializer):
return serializer.save(hospital=self.request.user)
def get_queryset(self):
return self.queryset.filter(hospital=self.request.user)
class PatientCardDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = PatientsCardSerializer
permission_classes = (permissions.IsAuthenticated, IsOwner,)
queryset = Card.objects.all()
lookup_field = "id"
def get_queryset(self):
return self.queryset.filter(hospital=self.request.user)
I have made this function that runs every time a user logs in. I want to get the branch from 'user' but every time the session is set it's only available to the function even after setting it to BRANCH_ID in the settings file. any help? plus I don't want to do anything in view function with the request as it's not accessible from models
EDIT
I have added all the models
def perform_some_action_on_login(sender, request, user, **kwargs):
"""
A signal receiver which performs some actions for
the user logging in.
"""
request.session[settings.BRANCH_ID] = user.profile.branch_id
branch = request.session.get(settings.BRANCH_ID)
print(branch)
user_logged_in.connect(perform_some_action_on_login)
class WaybillTabularInlineAdmin(admin.TabularInline):
model = WaybillItem
extra = 0
# form = WaybillItemForm
fk_name = 'waybill'
autocomplete_fields = ('product',)
class WaybillAdmin(admin.ModelAdmin):
list_display = (
'from_branch',
'to_branch',
'updated_by',
)
list_filters = (
'from_branch',
'to_branch',
'product',
)
inlines = [WaybillTabularInlineAdmin]
readonly_fields = ("updated_by",)
what I was trying to do is products by the branch
class Waybill(models.Model):
from_branch = models.ForeignKey(
Branch,
default=1,
on_delete=models.CASCADE, related_name='from_branch')
to_branch = models.ForeignKey(
Branch, on_delete=models.CASCADE, related_name='to_branch')
comments = models.CharField(max_length=1024, blank=True)
created_date = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(
User, on_delete=models.CASCADE,
blank=True, null=True,
related_name='waybill_created')
updated = models.BooleanField(default=False)
updated_by = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='waybill_user')
def __str__(self):
return 'from {} to {}'.format(
self.from_branch.branch_name,
self.to_branch.branch_name,
)
class WaybillItem(models.Model):
waybill = models.ForeignKey(Waybill, on_delete=models.CASCADE)
product = models.ForeignKey(ProductDetail, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
def __str__(self):
return 'from {} to {}'.format(
self.waybill.from_branch,
self.waybill.to_branch
)
class Product(models.Model):
item = models.ForeignKey(
Item, on_delete=models.CASCADE, related_name="product")
branch = models.ForeignKey(
Branch, default=1, on_delete=models.CASCADE)
in_stock = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
objects = ProductManager()
class Meta:
verbose_name = "Inventory"
verbose_name_plural = "Inventories"
ordering = ("-created_date",)
constraints = [
models.UniqueConstraint(
fields=['item', 'branch'], name='unique product'),
]
def __str__(self):
return self.item.item_description
class ProductDetail(models.Model):
ITEM_CONDITION_CHOICES = (
("NEW", "New"),
("BROKEN", "Broken"),
("FAIRLY USED", "Fairly Used"),
)
condition = models.CharField(max_length=12, choices=ITEM_CONDITION_CHOICES,
default=ITEM_CONDITION_CHOICES[0][0])
product = models.ForeignKey(Product, on_delete=models.CASCADE)
short_description = models.CharField(max_length=255, blank=True)
color = models.CharField(max_length=15, blank=True)
bought_price = models.PositiveIntegerField(default=0.00)
sales_price = models.PositiveIntegerField(default=0.00)
retail_price = models.PositiveIntegerField(default=0.00)
item_code = models.CharField(max_length=15, default=0)
item_model_number = models.CharField(max_length=20, default=0)
quantity = models.PositiveIntegerField(default=0)
manufacturer_website = models.CharField(max_length=255, blank=True)
generated_url = models.CharField(max_length=255, blank=True)
created_date = models.DateTimeField(default=timezone.now)
updated_date = models.DateTimeField(auto_now=True)
# objects = ProductDetailManager()
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()