Model defines __str__, how can I access the primary_key value? - python

I'm doing a web app using django and jinja2.In my models.py my class defines the __str__ function, to return a friendly text when referring to the objects of that class.
class MySystem (models.Model):
system_id = models.AutoField(primary_key=True),
system_name = models.CharField(max_length=100)
parent_system = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL)
def __str__(self):
return "{} > {}".format(self.parent_system, self.system_name)
class Detail (models.Model):
detail_id = models.AutoField(primary_key=True)
system_id = models.ForeignKey(MySystem, on_delete=models.DO_NOTHING)
title = models.CharField(max_length=150)
def __str__(self):
return "{} > {}".format(self.system_id, self.title)
I have a Detail object, and I want the ID of its system. When I try to access the primary key, it returns the string instead of the ID.
<td> <a href="/base/system/{{detail.system_id}}" > {{ detail.system_id.system_name }} </a> </td>
I tried detail.system_id.system_id and it returns django.db.models.fields.AutoField. I want it to return the numeric ID for the link.

Ok, I found my solution. What I need to do is detail.system_id.id.

Related

How to print data in template django of a diffrent table joined by foreign key?

Hello Everyone i have Two model first one is as following:
class Item(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
bargainprice = models.FloatField(default=0)
discount_price = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField()
and i am getting this model data using the following view:
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
and in product.html i am accessing Item objects like this:
<span class="mr-1">
<del>₹ {{ object.price }}</del>
</span>
<span>₹ {{ object.discount_price }}</span>
{% else %}
<span> ₹ <span id="pp">{{ object.price }}</span></span>
and so on..
everything working fine up here. but problem arises when i created the following model:
class BargainModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
itemId = models.IntegerField()
bprice = models.FloatField()
i joined this with foreign key as mentioned.
**what i want to do is print the " bprice " in the product.html of the same user but i am not able to do it **
can anyone help me with this i am new to Django.
Thanks in advance
in this case you need to import User like
from django.contrib.auth.models import User
class BargainModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
itemId = models.ForeignKey(Item, on_delete=models.CASCADE)
bprice = models.FloatField()
in product.html you can call the model of BargainModel it also contains the Item with user
It is better to work with a ForeignKey since this will guarantee referential integrity. You thus shoudl define the BargainModel as:
from django.conf import settings
class Bargain(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
item = models.ForeignKey(
Item,
on_delete=models.CASCADE
)
bprice = models.FloatField()
class Meta:
constraints = [
models.UniqueConstraint(fields=['item', 'user'], name='unique_user_item')
]
In the DetailView, we can then look if there is a Bargain record for the given item and user with:
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
def get_bargain(self):
if self.request.user.is_authenticated():
return Bargain.objects.filter(item=self.object, user=request.user).first()
Then you can render this with:
{{ view.get_bargain.bprice }}
if there is a related Bargain, then it will show the corresponding bprice.
Note: Models normally have no Model suffix. Therefore it might be better to rename BargainModel to Bargain.

Django get subobjects in view

My two models:
class BusinessType(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=200)
description = models.CharField(max_length=200)
class Business(models.Model):
def __str__(self):
return self.name
name = models.CharField(max_length=200)
description = models.CharField(max_length=200)
bus_type = models.ForeignKey(BusinessType, on_delete=models.CASCADE, name="type")
class Appointment(models.Model):
from datetime import datetime
business = models.ForeignKey(Business, on_delete=models.CASCADE, name="appointments")
done = False
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Now I add this context to my view:
'business':Business.objects.order_by('name'),
My template:
{{business|length}}<hr />
{%for business_entry in business%}
{{business_entry.appointments.all|length}}
{%endfor%}
Now the business length outputs "2" and that's right, I have two business objects.
But for the appointments I get the value "0" which is not true.
What am I doing wrong?
It should be related_name="appointments", not name="appointments".
So, change:
business = models.ForeignKey(Business, on_delete=models.CASCADE, name="appointments")
To:
business = models.ForeignKey(Business, on_delete=models.CASCADE, related_name="appointments")
You might want to read: ForeignKey.related_name

Django - Get name of model object by iterating through class

I'm new to Python (and pretty inexperienced at programming in general), but I have an issue I can't for the life of me figure out.
I'm trying to pre-populate a field in my database with the name of an instance from another model/class in my database. The model with the field I want to pre-populate is an "instance" of the model instance from which I'm trying to grab the name, and has a foreign key to that instance.
Goal: 1) User selects the parent of the object by assigning the foreign key to the parent 2) A function grabs the name of the parent instance matching the foreign key the user selected. 3) the result from that function is used as the default value for the field.
Here's the code:
class Injury(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular injury')
name = models.CharField(max_length=200, help_text='Enter an injury or complication (e.g. respiratory failure)')
description = models.TextField(max_length=1000, blank=True, help_text='Describe the injury')
time_to_onset = models.PositiveIntegerField(blank=True, validators=[MaxValueValidator(10000)], help_text='Enter expected time from trigger until injury/complication onset')
findings = models.TextField(max_length=1000, blank=True, help_text='Enter the signs and symptoms of the injury or complication')
vitals_trends = models.TextField(max_length=1000, blank=True, help_text='Enter the vitals changes due to the injury')
class Meta:
ordering = ['name']
def __str__ (self):
return self.name
def get_absolute_url(self):
return reverse('Injury-detail', args=[str(self.id)])
class Injury_Instance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular injury')
parent_case = models.ForeignKey(PFC_Case, on_delete=models.SET_NULL,null=True)
injury_model = models.ForeignKey(Injury, on_delete=models.SET_NULL, null=True)
def set_injury_name(self):
for injuries in Injury.all()
if injury_model == injuries
break
return Injury.name
name = dislay_models.CharField(default=set_injury_name(self,Injury,injury_model), max_length=100)
triggered_by = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True)
def __str__ (self):
return self.name
def get_absolute_url(self):
return f'{self.id} ({self.Injury.name})'
The problem area is def set_injury_name and Injury_Instance.name
Thanks!!!
Edit:
I tried the following code, but I'm getting the error 'NameError: name 'self' is not defined'
class Injury_Instance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular injury')
parent_case = models.ForeignKey(PFC_Case, on_delete=models.SET_NULL,null=True)
injury_model = models.ForeignKey(Injury, on_delete=models.SET_NULL, null=True)
def get_injury_name(self):
return self.name
injury_name=get_injury_name(self)
name = models.CharField(default=injury_name, max_length=100)
triggered_by = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True)
def __str__ (self):
return self.name
def get_absolute_url(self):
return f'{self.id} ({self.Injury.name})'
You don't need to store the name of your foreign key field as you always can access it with:
self.injury_model.name
If you need to get access it just by name you can write a property in Injury_Instance model.
#property
def name(self):
return self.injury_model.name

Django - form with foreign key to model with gallery

I have models like this:
class Picture(models.Model):
source = models.ImageField(null=True, blank=True) #TODO: check the field type, correct if needed
def __str__(self):
return "%s" % self.pk
class News(models.Model):
content = MartorField()
title = models.CharField(max_length=512)
creation_date = models.DateField(default=timezone.now)
publish_date = models.DateField(null=True, blank=True)
picture_id = models.ForeignKey('Picture', null=True, blank=True, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "News"
def __str__(self):
return "%s" % self.title
And I'm using CreateView and UpdateView. When I use {{ form.as_p }} I have a problem, because picker of image is showing only id - not image. I'm looking for some widget or workaround to fix this problem.

Make model field equal concatenation of two fields in Django

I have two models and want to create a field for the second class that is a concatenation of a foreign field and a field within the model.
The code I have so far is:
class Drug(models.Model):
drug_name = models.CharField("Drug Name", max_length=200)
reference_title = models.CharField("Publication Title",max_length=1024)
pub_date = models.DateField("Pubication Date",'date published')
pubmed_link = models.CharField("PubMed Link", max_length=300)
class Risk(models.Model):
drug_link = models.ForeignKey(Drug, on_delete=models.CASCADE)
dosage = models.IntegerField(default=0)
independent_risk = models.DecimalField("Individual Risk", max_digits=4, decimal_places=2)
I want to add a new field to the Risk model that is automatically populated by a concatenation of the selected value for drug_link and the entered value for dosage.
This can be accomplished by a python property on the class:
class Risk(models.Model):
drug_link = models.ForeignKey(Drug, on_delete=models.CASCADE)
dosage = models.IntegerField(default=0)
independent_risk = models.DecimalField("Individual Risk", max_digits=4, decimal_places=2)
#property
def name_dosage(self):
return "%s - %s" % ( self.drug_link.drug_name, self.dosage )
If you do not need to store this value in database but rather use it in templates, you would not need to create extra fields. You can use methods like this:
class Risk(models.Model):
drug_link = models.ForeignKey(Drug, on_delete=models.CASCADE)
dosage = models.IntegerField(default=0)
independent_risk = models.DecimalField("Individual Risk", max_digits=4, decimal_places=2)
def dosages(self):
return "{} - {}".format(self.drug_link.drug_name, self.dosage)
And in the templates, you can just do:
{% for risk in risks %}
{{ risk.dosage }}
{% endfor %}

Categories