Override the variable from parent class in Django Models - python-3.x

I have a model ChildModel and it has two parent classes ActivatorModel and TimeStampedModel
Below are the three models:
The two base classes
class ActivatorModel(models.Model):
"""
ActivatorModel
An abstract base class model that provides activate and deactivate fields.
"""
INACTIVE_STATUS = 0
ACTIVE_STATUS = 1
STATUS_CHOICES = (
(INACTIVE_STATUS, _('Inactive')),
(ACTIVE_STATUS, _('Active')),
)
status = models.IntegerField(_('status'), choices=STATUS_CHOICES, default=ACTIVE_STATUS)
activate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for an immediate activation'))
deactivate_date = models.DateTimeField(blank=True, null=True, help_text=_('keep empty for indefinite activation'))
objects = ActivatorModelManager()
class Meta:
ordering = ('status', '-activate_date',)
abstract = True
def save(self, *args, **kwargs):
if not self.activate_date:
self.activate_date = now()
super().save(*args, **kwargs)
class TimeStampedModel(models.Model):
"""
TimeStampedModel
An abstract base class model that provides self-managed "created" and
"modified" fields.
"""
created = CreationDateTimeField(_('created'))
modified = ModificationDateTimeField(_('modified'))
def save(self, **kwargs):
self.update_modified = kwargs.pop('update_modified', getattr(self, 'update_modified', True))
super().save(**kwargs)
class Meta:
get_latest_by = 'modified'
abstract = True
The class using the above base models
class ChildModel(ActivatorModel, TimeStampedModel):
child_id = models.CharField(
max_length=36, primary_key=True, default=uuid.uuid4
)
display_name = models.CharField(blank=True, max_length=100, null=True)
status = models.CharField(max_length=20, null=True, blank=True, default='Active')
The issues is whenever I try to save some character type value in ChildModel.status, it throws an error
invalid input syntax for integer.
How to properly override the variable status and have it the properties defined in the ChildModel?

Related

"<VariationPrice>" needs to have a value for field "id" before this many-to-many relationship can be used

I have this model in my django code. I want to check whether VariationPrice for a product with the variations exist. If it exists, make changes to the already existing VariationPrice else save the new VariationPrice.
The error I'm getting on saving new VariationPrice is
"<VariationPrice: >" needs to have a value for field "id" before this many-to-many relationship can be used.
The code I have in models.py is:
class Product(models.Model):
....
product_name = models.CharField(max_length=200, unique=True)
class Variation(models.Model):
....
variation_value = models.CharField(max_length=100)
class VariationPrice(models.Model):
price = models.IntegerField()
product = models.ForeignKey(Product, on_delete=models.CASCADE)
variations = models.ManyToManyField(Variation, blank=True)
def __str__(self):
if self.pk is not None:
return ", ".join(str(var) for var in self.variations.all())
else:
return ''
def save(self, *args, **kwargs):
if self.pk is None:
var_list = [i['variation_value'] for i in self.variations.values()]
vprice = VariationPrice.objects.filter(product=product,variations__variation_value__in=var_list).annotate(num_attr=Count('variations__variation_value')).filter(num_attr=len(var_list))
if vprice.exists():
self.pk = vprice.first().pk
super(VariationPrice, self).save(*args, **kwargs)

'CourseTake' object has no attribute 'points'

models.py
class Course(models.Model):
title = models.CharField(max_length=255)
credit_hours = models.IntegerField()
instructor = models.ForeignKey(Instructor, on_delete=models.SET_NULL, null=True, related_name='course')
def __str__(self) -> str:
return self.title
class CourseTake(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='coursetake') #similar to reviews in the product class
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='course')
grade = models.PositiveIntegerField()
class Meta:
unique_together = [['student', 'course']]
class SimpleCourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ['title','credit_hours']
class CourseTakeSerializer(serializers.ModelSerializer):
course = SimpleCourseSerializer()
points = serializers.SerializerMethodField()
grade_points = serializers.SerializerMethodField()
class Meta:
model = CourseTake
fields = ['id','course', 'grade', 'points', 'grade_points']
def get_points(self, coursetake: CourseTake):
if coursetake.grade >= 90:
return '4'
elif coursetake.grade >= 70:
return '3'
elif coursetake.grade >= 50:
return '2'
return '1'
#TRY AND ERROR
#Terminal: 'CourseTake' object has no attribute 'points'
def get_grade_points(self, coursetake: CourseTake):
return coursetake.course.credit_hours * coursetake.points
I want to calculate grade points, which will be used later to calculate each student's GPA score. So the get_grade_point()  will return the credit_hours *  points. My problem is that the points field is not part of the model or serializer. I created a function to calculate the points for each course. Because I defined the points, Django keeps saying it's not an attribute anytime I try to access the point values. Is there a way to access the points value inside the get_grade_function?
Image for better view
Depends on what you want I suggest to use
Save method on model
def save(self, *args, **kwargs):
If you want to save result in database, Or you can use #proparty to make read only method also inside your model class if you don’t want to save it
After that you can use it easily in serializer

Attribute Error: Object has no Attributes while trying to update the manytoo

Attribute Error: Object has no Attributes "avg_rating"
Errors occurs while trying to update the ManytooOne Field in views.py perform_create func.
Imm trying to update a avg_rating which is instance of Review model, Every time an a comment is received. my review is related to watchlist through foreign key.
Here's my models.py
class WatchList(models.Model):
title = models.CharField(max_length=50)
storyline = models.CharField(max_length=200)
platform = models.ForeignKey(StreamPlatform, on_delete=models.CASCADE, related_name="watchlist")
active = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Review(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
rating = models.PositiveIntegerField(validators = [MinValueValidator(1), MaxValueValidator(5)])
comment = models.CharField(max_length=200, null=True)
watchlist = models.ForeignKey(WatchList, on_delete=models.CASCADE, related_name="reviews")
avg_rating = models.FloatField(default=0)
num_rating = models.IntegerField(default=0)
active = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.comment
serializer.py
class ReviewSerializer(serializers.ModelSerializer):
username = serializers.StringRelatedField(read_only=True)
class Meta:
model = Review
exclude = ["watchlist"]
class WatchListSerializer(serializers.ModelSerializer):
### using relation serializer to list all the reviews in a movie
reviews = ReviewSerializer(many=True, read_only=True)
class Meta:
model = WatchList
fields = "__all__"
views.py
class ReviewCreateView(generics.CreateAPIView):
serializer_class = ReviewSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return Review.objects.all()
def perform_create(self, serializer):
##posting the comment in a movie using movies primary key
primary_key = self.kwargs.get("pk")
watchlist = WatchList.objects.get(pk=primary_key)
#NOt allowing the same user to comment on the same movie twice
username = self.request.user
review_queryset = Review.objects.filter(watchlist=watchlist, username=username)
if review_queryset.exists():
raise ValidationError("You cannot comment on the same movie Twice")
##NOTE: want to updated this section
if watchlist.avg_rating == 0:
watchlist.avg_rating = serializer.validated_data['avg_rating']
else:
watchlist.avg_rating = (watchlist.avg_rating + serializer.validated_data['avg_rating'])/2
watchlist.num_rating += 1
watchlist.avg_rating.save()
serializer.save(watchlist=watchlist, username=username)

QuerySet django . How to write a function correctly to make tests pass

how returns in tree_downwards the root organization with the requested org_id and all its children at any nesting level and returns in tree_upwords the root organization with the requested org_id and all its parents at any nesting level to make tests pas???
I will only be able to return either the parents or the organization itself
models.py
class OrganizationQuerySet(models.QuerySet):
def tree_downwards(self, root_id):
"""
:type root_org_id: int
"""
return self.filter(???)
def tree_upwards(self, child_id):
"""
:type child_org_id: int
"""
return self.filter(???)
class Organization(models.Model):
objects = OrganizationQuerySet.as_manager()
name = models.CharField(max_length=1000, blank=False, null=False)
parent = models.ForeignKey(
"self", null=True, blank=True, on_delete=models.PROTECT
)
class Meta:
ordering = ["name"]
verbose_name = "organization"
def __str__(self):
return self.name
tests.py
def test_get_tree_downwards_cluster(make_organization):
org_1 = make_organization()
org_2 = make_organization(parent=org_1)
children = Organization.objects.tree_downwards(org_1.id)
assert org_1 in children
assert org_2 in children
def test_get_parents_chain(make_organization):
org_1 = make_organization()
org_2 = make_organization(parent=org_1)
org_3 = make_organization(parent=org_2)
parents = Organization.objects.tree_upwards(org_3.id)
assert org_1 in parents
assert org_2 in parents
assert org_3 in parents
Does it have to be a QuerySet? I would implement it as follows:
from django.db import models
class Organization(models.Model):
name = models.CharField(max_length=1000, blank=False, null=False)
parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.PROTECT, related_name='children')
class Meta:
ordering = {'name'}
verbose_name = 'organization'
def __str__(self):
return self.name
#property
def tree_upward(self):
result = [self]
if self.parent:
result += self.parent.tree_upward
return result
#property
def tree_downward(self):
result = [self]
for child in self.children.all():
result += child.tree_downward
return result
In the answer from #physicalattraction you get a very nice interface for the Organization model. If you really need to return a QuerySet, you could "cast" the list into a QuerySet like this:
class Organization(models.Model):
# other code
#classmethod
def _cast_to_queryset(cls,list):
'''method to cast list of objects into queryset'''
castlist = [rec.id for rec in list]
queryset = cls.objects.filter(id__in=castlist)
return queryset
#property
def tree_upward(self):
result = [self]
if self.parent:
result += self.parent.tree_upward
return Organization._cast_to_queryset(result) # <-- cast to queryset
#property
def tree_downward(self):
result = [self]
for child in self.children.all():
result += child.tree_downward
return Organization._cast_to_queryset(result) # <-- cast to queryset
I think this would work nicely and retain the nice interface that #physicalattraction set up for you in his answer.

Django admin filter foreign key

I have 4 class:
class Material(models.Model):
name = models.CharField(_('name'), max_length=50)
class Property(models.Model):
name = models.CharField(_('name'), max_length=50)
class Physic(models.Model):
name = models.ForeignKey(Property, verbose_name=_('name'), null=True, blank=True,)
lapropriete = models.CharField(_('property'), max_length=100)
class UniteProperty2(models.Model):
name = models.ForeignKey(Material, verbose_name=_('name'))
nature_unit = models.ForeignKey(Property, verbose_name=_('category'))
choix = models.ForeignKey(Physic, verbose_name=_('properties'), null=True, blank=True, related_name='choix')
What I want to do is when I am selecting nature_unit in UniteProperty2 it shows only properties (in administration interface)
that belong to the current category '
(ex: if i select Mechanical, i will have 'Hardness vickers', 'young Modulus', Maximum stress' in the dropdown list 'choix')
in the admin.py file, I have
class UniteProperty2InlineForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UniteProperty2InlineForm, self).__init__(*args, **kwargs)
self.fields['choix'].queryset = Physic.objects.filter(
name=self.instance.name)
class UniteProperty2Inline(admin.TabularInline):
model = UniteProperty2
form = UniteProperty2InlineForm
class MaterialAdmin(admin.ModelAdmin):
inlines = (UniteProperty2Inline, ..)
but it doesn't work...i have the error 'No exception supplied' Exception Type: DoesNotExist
the problem is : name__name=self.instance.name
self.instance.name - in ur form refers to UniteProperty2 name - which is a Material obj
so try this
self.fields['choix'].queryset = Physic.objects.filter(
name=self.instance.choix )
or for all options:
self.fields['choix'].queryset = Physic.objects.filter(
name=self.instance.choix )

Resources