def __str__ on model - django

I'm looking to return a str on this model that is equal to industry name + risk level (i.e. Low)
RISKLEVEL = (
(0, "Low"),
(1, "Medium"),
(2, "High"),
)
class IndustryIndex(models.Model):
industry = models.CharField(max_length=200)
risk = models.IntegerField(choices=RISKLEVEL)
description = models.CharField(max_length=200)
def __str__(self):
return self.industry + self.page
I know that my syntax on the line under def __str__(self): isn't correct. Do you know what it should be? Also, self.page only seems to return the integer, but I'm interested in returning the description (i.e. 'High').
Thanks!

You can use get_risk_display() method:
def __str__(self):
return '{}-{}'.format(self.industry, self.get_risk_display())

Related

Django Custom model method with parameters, NON DRY

After much research and trouble i came up with a non DRY solution, Hope someone can make it DRY.
All im trying to get is a calculated Price which takes a parameter and displays in the template accordingly.
i have a function get_price on model vehiclecategory which takes a parameter duration which is received from frontend forms.
MODELS.PY
class VehicleCategory(models.Model):
CATEGORY_CHOICES=(
('E-Cycle', 'E-Cycle'),
('E-Scooter', 'E-Scooter')
)
main_category = models.CharField(max_length=15, choices= CATEGORY_CHOICES)
title = models.CharField(unique=True, max_length=200)
image = models.ImageField(
null=True,
blank=True,
width_field="width_field",
height_field= "height_field",
default= 'e-bike.png',
upload_to='category')
width_field = models.IntegerField(default=250)
height_field = models.IntegerField(default=250)
slug =models.SlugField(max_length=200, db_index=True, unique=True)
def __str__(self):
return self.title
#GET PRICE
def get_price(self, duration):
for item in VehiclePrice.objects.all():
if item.vehicle_category.title == self.title and (duration >= item.slab.start and duration <= item.slab.end):
return item.total_price
class Meta():
verbose_name = "Vehicle Category"
verbose_name_plural = "Vehicle Categories"
class PriceSlab(models.Model):
start = models.IntegerField()
end = models.IntegerField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s ' % (self.start, self.end)
class VehiclePrice(CustomerStatus):
help_text= "Ensure no more than 2 digits after decimal"
vehicle_category = models.ForeignKey(VehicleCategory, on_delete= models.SET_NULL, null=True, related_name='vehicle_category_price')
slab = models.ForeignKey(PriceSlab, on_delete=models.CASCADE)
net_price = models.DecimalField(help_text= help_text, max_digits=5, decimal_places=2)
tax_percent = models.DecimalField(help_text=help_text, max_digits=4, decimal_places=2, default=18.00)
discount_percent = models.DecimalField(help_text=help_text,max_digits=4, decimal_places=2, default=0, blank=True)
#property
def total_tax(self):
tax = (self.net_price * self.tax_percent)/100
return tax
#property
def get_price(self):
total = self.net_price + self.total_tax
return total
#property
def total_discount(self):
discount = (self.get_price * self.discount_percent)/100
return discount
#property
def total_price(self):
total = self.get_price - self.total_discount
return round(total)
class Meta():
unique_together=('customer_status','vehicle_category' ,'slab')
def __str__(self):
return '%s - %s - %s' % (self.customer_status, self.vehicle_category, self.slab)
VIEWS.PY
class HomeView(ListView):
template_name = 'app/home.html'
def get(self, request):
if request.method == "GET":
start_date = request.GET.get('start_date')
end_date = request.GET.get('end_date')
if start_date and end_date:
start_date = datetime.strptime(start_date, "%d/%m/%Y").date()
end_date = datetime.strptime(end_date, "%d/%m/%Y").date()
duration = (end_date - start_date).days +1
print(duration)
vehiclecategory= VehicleCategory.objects.all()
context = {
'price1': VehicleCategory.objects.get(main_category= 'E-Cycle', title="Sporty").get_price(duration),
'price2': VehicleCategory.objects.get(main_category= 'E-Cycle', title="Step-Through").get_price(duration),
'price3': VehicleCategory.objects.get(main_category= 'E-Cycle', title="Fatbike").get_price(duration),
'price4': VehicleCategory.objects.get(main_category= 'E-Scooter', title="Scooter").get_price(duration),
'vehiclecategory1': vehiclecategory.filter(main_category= 'E-Cycle', title="Sporty"),
'vehiclecategory1': vehiclecategory.filter(main_category= 'E-Cycle', title="Step-Through"),
'vehiclecategory1': vehiclecategory.filter(main_category= 'E-Cycle', title="Fatbike"),
'vehiclecategory2': vehiclecategory.filter(main_category= 'E-Scooter', title="Scooter"),
'form':CartQuantityForm(),
'dateform': DateForm(),
}
else:
context={'dateform': DateForm(),}
return render(request, self.template_name, context )
after the user inputs the date range, the vehicles are displayed, but when u go to the cart and come back the same page, the page refreshes as a new one. how can keep the date range values intact and render the same page as the user got first time he searched for a vehicle, so that he can add or modify the vehicles selected???
You may put your start & end dates into your URL.
You can create 2 urls record dispatching the same view:
path(r'/prices/', HomeView.as_view())
path(r'/prices/(?P<start>\d{4}-\d{2}-\d{2})_(?P<end>\d{4}-\d{2}-\d{2})', HomeView.as_view())
Then you need to make some changes in your view:
class HomeView(ListView):
template_name = 'app/home.html'
def get(self, request, **kwargs):
start = kwargs.get('start')
end = kwargs.get('end')
if start is None or end is None:
# Ask for dates & Redirect to its new url with dates.
else:
# Check the dates, convert them to date object & do the rest.
Maybe not the best solution but the first thing came to my mind is this one.

How to join 2 attributes to create a name in Django model instance?

I have a model:
class Subject(models.Model):
level = models.CharField(choices=LEVEL_CHOICES, max_length=2)
subject_name = models.CharField(max_length=50)
teacher_name = models.ForeignKey(Teacher, on_delete=models.CASCADE)
total_seats = models.IntegerField()
subject_details = models.CharField(max_length=100)
subject_img = models.ImageField()
I want to display each instance as level and then subject name. For example, if the instance has a level 'Advanced' and subject_name as 'Physics', I want the instance to be displayed as 'Advanced Physics'.
I have tried using str method but it shows subject_name is not defined:
def __str__(self):
return self.level+ ''+ subject_name
EDIT:
I forgot to mention that level field takes in choices, as so:
LEVEL_CHOICES = (
('09', 'Class 9 O level'),
('10', 'Class 10 O level'),
('11', 'AS level'),
('12', 'A2 level'),
)
How do I display the data that is visible to human? ie. the ones on the right as the level
These are attributes defined on the self object, so you implement this as:
def __str__(self):
return self.level + '' + self.subject_name
or you perhaps can use string formatting here:
def __str__(self):
return f'{self.level}{self.subject_name}'
If you want to use the display value for the choice of level, you can call the get_level_display method:
def __str__(self):
return self.get_level_display() + '' + self.subject_name
You need to refer to self to access subject_name as such:
def __str__(self):
return self.level + ' ' + self.subject_name
or formatted via Python3:
def __str__(self):
return '{0} {1}'.format(self.level, self.subject_name)
and to get the human readable value, you can simply use the .get_FOO_display() method:
def __str__(self):
return '{0} {1}'.format(self.get_level_display(), self.subject_name)
Model.get_FOO_display(): https://docs.djangoproject.com/en/3.0/ref/models/instances/#django.db.models.Model.get_FOO_display

Not able to calculate to what range current date belongs in django?

I have period model and this model has a current property that should calculate what period is current.
#with_author
class Period(CommonInfo):
version = IntegerVersionField( )
order_value = models.PositiveSmallIntegerField()
start_date = models.DateField()
end_date = models.DateField()
name = models.CharField(max_length=30)
duration = models.PositiveSmallIntegerField(null=True, blank=True)
is_special = models.BooleanField(default=False)
is_marked = models.BooleanField(default=False)
_is_current = models.NullBooleanField( blank=True, null=True, default=None)
def __unicode__(self):
return u'%s %i %s ' % ("#", self.order_value, self.name)
def _is_current(self):
if self.start_date <= datetime.datetime.now().date() <= self.end_date:
self._is_current = True
else:
self._is_current = False
#property
def is_current(self):
if self._is_current is None:
self._is_current()
return self._is_current
However it is not calculated and I am not getting any error. What I am doing wrong?
First, you need to change the name of your method, because it is the same as one of your database fields (i.e., self._is_current refers to refers to your NullBooleanField and to your method for checking if the period is current. Also, you need to callsave() after updating a field. Try updating (and renaming) your _is_current() method as follows:
def period_is_current(self):
if self.start_date <= datetime.datetime.now().date() <= self.end_date:
self._is_current = True
else:
self._is_current = False
self.save()
This is very confusing. I would just use the property:
#property
def is_current(self):
if not self._is_current:
self._is_current = (self.start_date <= datetime.datetime.now().date() <= self.end_date)
self.save()
return self._is_current

django sort on calculated model field -- can I use .extra?

I have the model below. I want to order by percent_vote. I know I could calculate the value and save to a new field in the model, but I prefer not to go that way. Is there some way to use .extra method to do this?
Django 1.6, sqlite3
class HallOfFame(models.Model):
player = models.ForeignKey(Master)
year = models.IntegerField(db_index=True)
voted_by = models.CharField(max_length=30)
ballots_cast = models.IntegerField()
votes_needed = models.IntegerField()
votes_received = models.IntegerField(db_index=True)
inducted = models.BooleanField(db_index=True)
category = models.CharField(max_length=30, db_index=True)
needed_note = models.CharField(max_length=75, blank=True, null=True)
def __unicode__(self):
return "%s %s" % (self.player.name_first, self.player.name_last)
def percent_vote(self):
try:
return self.votes_received/float(self.ballots_cast)
except ZeroDivisionError:
return 0
Yes, it seems you can do something like this, but this may depend on the your database backend ( this should work for PostgreSQL ):
q = HallOfFame.objects.extra(select={'percent_vote_integer': "votes_received/ballots_cast", 'percent_vote_remainder': "votes_received%ballots_cast"})
q = q.extra(order_by = ['percent_vote_integer', percent_vote_remainder])
I ended up solving this issue with the code below. #Emil Davtyan's answer didn't work for me, and I wanted to figure out a more general solution.
def home(request):
hall = HallOfFame.objects.filter(inducted=True, voted_by='BBWAA')
hall_sorted = sorted(hall, key=lambda member: member.percent_vote, reverse=True)[:20]
return render_to_response('top_lists.html', {'hall': hall_sorted })
the model has this:
#property
def percent_vote(self):
try:
return float(self.votes_received)/self.ballots_cast
except ZeroDivisionError:
return 0

How to change value of the field in a proxy model in Django

I have a base model, and proxy models. I want to change value of upload_to of 'image' filed, that depends on 'file_type' filed.
I'm not sure how to do this, do I need to specify it in my .Manager class or in Proxy class.
Can you please give me same detail how to do this.
class FileDescription(models.Model):
class Meta:
ordering = ['file_creation_time']
TYPE_CHOICES = (
('homework', 'Homework'),
('class', 'Class Papers'),
('random', 'Random Papers')
)
subject = models.ForeignKey('Subjects', null=True, blank=True, primary_key=True)
subject_name = models.CharField(max_length=100, unique=False)
file_type = models.CharField(max_length=100, choices=TYPE_CHOICES)
....
....
image = models.ImageField(upload_to= ??????????? blank=True, null=True, max_length=255)
def __unicode__(self):
return u'%s' % (self.file_name)
class HomeworkManager(models.Manager):
def get_query_set(self):
qs = super(HomeworkManager, self).get_query_set().filter(file_type='homework')
return qs
class ClassPapersManager(models.Manager):
def get_query_set(self):
qs = super(HomeworkManager, self).get_query_set().filter(file_type='class')
return qs
class RandomPapersManager(models.Manager):
def get_query_set(self):
qs = super(HomeworkManager, self).get_query_set().filter(file_type='random')
return qs
class Homework(FileDescription):
class Meta:
proxy = True
Don't worry about replacing upload_to just modify the method to handle different subclasses (use a method for upload_to if you're not already).
def my_upload_to(instance, filename):
if instance._meta.module_name == 'homework':
return '/path/to/homework/files/%s' % filename
if instance._meta.module_name == 'classpaper':
return '/path/to/classpaper/files/%s' % filename
if instance._meta.module_name == 'randompaper':
return '/path/to/randompaper/files/%s' % filename