Django Retrieve Data From Two Tables By Join - django

Hi I have two tables which are Employee(eid,eName,contact_num,e-mail,adress,salary) and Nurse(nurse_id,e_id) and the "e_id" column of Nurse model has foreign key on 'eid' of Employee model.I know how to filter by specific id, however all of them as list so that, I want to return all nurses from Employee table.You can find my models below. I am new to Django that is why any help or hint is appreciated. Thanks in advance.
class Employee(models.Model):
eid = models.IntegerField(primary_key=True)
ename = models.CharField(db_column='eName', max_length=25) # Field name made lowercase.
contact_num = models.DecimalField(max_digits=12, decimal_places=0)
e_mail = models.CharField(max_length=30)
adress = models.CharField(max_length=250, blank=True, null=True)
salary = models.IntegerField()
class Nurse(models.Model):
nurse_id = models.IntegerField(primary_key=True)
e = models.ForeignKey(Employee, models.DO_NOTHING)

from an instance of employee class you can get the nurses as follows
employee_1 = Employee.objects.first()
nurses = employee_1.nurse_set.all()
can call in templates of list view of employee by
{% for obj in object_list %}
{{ obj.ename }}
{% for nurse in obj.nurse_set.all %}
{{ nurse.eid }}
{% endfor %}{% endfor %}

Related

Get Data from all objects of a queryset in django

I have three models Order, OrderEntries and Product
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
order_entries = models.ManyToManyField(OrderEntries, blank=True)
...
class OrderEntries(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField()
class Product(models.Model):
title = models.CharField(max_length=1000)
slug = models.SlugField(blank=True, null=True, unique=True)
Now, I have to get history of purchased products. As I can get all previous orders placed by a user like this
queryset = Order.objects.filter(user=self.request.user, client=self.request.client)
But how I can get list of products from all those orders?
If you specify a related_name on the ForeignKey field as follows:
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='products')
You could then access the products in your template, for example:
{% for order in orders %}
{% for order_entry in order.order_entries %}
{% for product in order_entry.products.all %}
{{ product }}
Please note: it isn't necessary to set related_name. If you don't set it, you can use BLA_set where BLA is the name of the field e.g.:
{% for product in order_entry.product_set.all %}
maybe this help :
product=[]
for e in queryset:
for ord in e['order_entries']:
for pr in ord['product'] :
product.append(pr)

How to retrieve data in Django model using related name and generic detail views

I am trying to display the data from one of my models to the DetailView using the related name defined in the model. It works for the Rental Property model but it doesn't work for the contract model. What might seems to be the problem?
A little context to what I am trying to achieve. To get the attribute's value of the rental model, I use a for loop on landlord.rentalproperty.all; rentalproperty been the related name to the landlord model. This work perfectly.
Where I am having a problem is when I use the contract model related name to rentalproperty, this doesn't work. How can I fixed that? Thanks.
my model:
UserModel = get_user_model()
class Landlord(models.Model):
user = models.OneToOneField(UserModel, on_delete=models.CASCADE)
address = models.CharField(max_length=255)
def __str__(self):
return str(self.address)
class RentalProperty(models.Model):
landlord = models.ForeignKey("Landlord", related_name='rentalproperty', on_delete=models.CASCADE)
created_by = models.ForeignKey(UserModel, related_name='rentalproperty', on_delete=models.CASCADE)
PROPERTY_LISTING_CHOICES = Choices(
('APARTMENT', _('Apartment')),
('HOLIDAY_HOME', _('Holiday home')),
('SINGLE_FAMILY_HOME', _('Single family home')),
('COMMERCIAL', _('Commercial')),
)
type_of_property_listing = models.CharField(
max_length = 50,
choices = PROPERTY_LISTING_CHOICES,
default = PROPERTY_LISTING_CHOICES.APARTMENT,)
street = models.CharField(max_length=255)
borough = models.CharField(max_length=255)
def __str__(self):
return str(self.type_of_property_listing)
class Contract(models.Model):
rentalproperty = models.ForeignKey("RentalProperty", related_name='contracts', on_delete=models.CASCADE)
insurance_required = models.BooleanField(default=True)
other_terms = models.TextField(blank=True)
def __str__(self):
return str(self.insurance_required)
My html:
<h1>This is the detail view</h1>
<h3>From landlord</h3>
<p>Address: {{landlord.address}}</p>
<h3>From Rental property</h3>
<ul>
{% for rental in landlord.rentalproperty.all %}
<li>landlord: {{rental.landlord}}</li>
<li>createdby: {{rental.created_by}}</li>
<li>Type of property: {{rental.type_of_property_listing}}</li>
<li>Street: {{rental.street}}</li>
<li>Borough: {{rental.borough}}</li>
{% endfor %}
</ul>
<ul>
{% for contract in rentalproperty.contracts.all %}
<li> rental property: {{contract.rentalproperty}}</li>
{% endfor %}
</ul>
My detail View.
class DetailView(generic.DetailView):
model = Landlord
template_name = 'rental/detail.html'
Here's a DetailView view:
class RentalPropertyDetailView(DetailView):
context_object_name = 'property'
model = models.RentalProperty
Notice the "context_object_name" attribute.
Second, your template is a little confusing.. Why would you want to loop for one landlord, listing the landlord's name again for each of its rental properties. And the the same for each contract?
Here's arentalproperty_detail.html template:
<h1>This is the detail view</h1>
<h3>From landlord: {{ property.created_by }}</h3>
<p>Address: {{ property.landlord.address }}</p>
<h3>From Rental property</h3>
<ul>
{% for rental in property.landlord.rental_properties.all %}
<br>
<li>createdby: {{rental.created_by}}</li>
<li>Type of property: {{rental.type_of_property_listing}}</li>
<li>Street: {{rental.street}}</li>
<li>Borough: {{rental.borough}}</li>
<ul>
{% for contract in rental.contracts.all %}
<li> Insurance required: {{contract.insurance_required}}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
Now a models.py:
class RentalProperty(models.Model):
landlord = models.ForeignKey("Landlord", related_name='rental_properties', on_delete=models.CASCADE)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
PROPERTY_LISTING_CHOICES = [
('APARTMENT', ('Apartment')),
('HOLIDAY_HOME', ('Holiday home')),
('SINGLE_FAMILY_HOME', ('Single family home')),
('COMMERCIAL', ('Commercial')),
]
type_of_property_listing = models.CharField(
max_length = 50,
choices = PROPERTY_LISTING_CHOICES,
default = 'APARTMENT',
)
street = models.CharField(max_length=255, default=None, null=True)
borough = models.CharField(max_length=255, default=None, null=True)
def __str__(self):
return str(self.type_of_property_listing)
class Contract(models.Model):
rental_property = models.ForeignKey("RentalProperty", related_name='contracts', on_delete=models.CASCADE)
insurance_required = models.BooleanField(default=True)
other_terms = models.TextField(blank=True)
def __str__(self):
return str(self.insurance_required)
The Landlord model I left it the same.
In urls.py you should fetch one (1) RetailProperty like:
url(r'^property/(?P<pk>\d+)$', views.RentalPropertyDetailView.as_view(), name='property-detail'),
This will output the following:

Django: want to loop through _set for pk values only

I'm stuck trying to figure out how to filter my template values with the detail view PK. I have a detail view for my employee. I wish to display my employee's subjects, where I then wish to filter the subjects with the evaluations that have been made for the subject.
I've gotten so far that I can show my subject names, and show all the evaluations for each subject. However, I don't want to show ALL of them I only want to show the ones that exist for the current employee (detailView PK). As you can see in my template, I'm using _set to make the relation, but I have no clue on how to filter the PK into that equation.
Example, what I want:
Subject 1:
Evaluationname - employee Johnny
Evaluationname - employee Johnny
Example, what I currently have:
Subject 1:
Evaluationname - employee Johnny
Evaluationname - employee Chris
I don't want Chris's evaluation, I only wish to filter the primary key, so in this case Johnny's evaluations.
Template
{% for subject in subject_list %}
{{ subject.subejctname }}
{% for evaluation in subject.evaluation_set.all %}
<div>
<p>{{ evaluering.ma }} | {{ evaluering.ma.firstname }} | {{ evaluering.ma.lastname }}</p>
</div>
{% empty %}
<p>No evaluations founds.</p>
{% endfor %}
{% endfor %}
View
class EmployeeDetailView(DetailView):
template_name = 'evalsys/employee/alle_employees_eval.html'
model = Employee
# Uses employee PK to make a detail view
def view_employee_with_pk(self, pk=None):
if pk:
employee = Employee.objects.get(pk=pk)
else:
employee = self.employee
args = {'employee': employee, }
return render(self, 'evalsys/employee/alle_employees_eval.html', args)
def get_context_data(self, **kwargs):
context = super(EmployeeDetailViewDetailView, self).get_context_data(**kwargs)
context['subject_list'] = Subject.objects.all()
return context
Subject Model
class Subject(models.Model):
id = models.AutoField(primary_key=True)
subjectname = models.CharField(max_length=255, help_text="Indtast navnet på faget.")
slug = models.SlugField(max_length=200, unique=True)
Evaluation model
class Evaluation(models.Model):
id = models.AutoField(primary_key=True)
employee_num = models.ForeignKey('Employee', on_delete=models.CASCADE, null=True)
subjectname = models.ForeignKey('Subject', on_delete=models.CASCADE, null=True)
Employee model
class Employee(models.Model):
id = models.AutoField(primary_key=True)
slug = models.SlugField(max_length=200)
employee_num = models.IntegerField(help_text="Indtast medarbejderens MA-nummer. (F.eks 123456)")
firstname = models.CharField(max_length=30, help_text="Indtast medarbejderens fornavn.")
lastname = models.CharField(max_length=30, help_text="Indtast medarbejderens efternavn.")
subjectname = models.ForeignKey('Subject', on_delete=models.CASCADE, null=True)
Reverse relationships (subject.evaluation_set) can be prefetched, this is a technique for reducing the number of database queries made when you access the reverse relationship for many objects in a queryset. When using the following queryset, when you access subject.evaluation_set.all it will not perform an additional DB access as the result has already been cached on each instance
Subject.objects.all().prefetch_related('evaluation_set')
This cached result can be modified by using Prefetch objects. Using these you can limit the contents of subject.evaluation_set.all to only contain the result that you want
Subject.objects.all().prefetch_related(
Prefetch(
'evaluation_set',
queryset=Evaluation.objects.filter(employee=self.employee)
)
)
Your model structure is confusing. Are you able to detail the relationship between employee, subject and evaluation?? You have mentioned you wish to display an employee's subjects, but via your model structure, an employee can have only one subject, as employee is related to the subject by a foreign key.
Below I have suggested some changes to your model names and your model structure so it might make more sense to retrieve your evaluations in the template. Feel free to ask questions about your model design as that is crucial to design your views, templates, etc.
Also please refer here for model naming conventions
Django Foreign Key Reference
Django Model Coding Style (PEP8)
Subject Model
class Subject(models.Model):
id = models.AutoField(primary_key=True)
subject_name = models.CharField(max_length=255, help_text="Indtast navnet på
faget.")
slug = models.SlugField(max_length=200, unique=True)
Employee Model
class Employee(models.Model):
id = models.AutoField(primary_key=True)
slug = models.SlugField(max_length=200)
employee_num = models.IntegerField(help_text="Indtast medarbejderens MA-nummer. (F.eks 123456)")
first_name = models.CharField(max_length=30, help_text="Indtast medarbejderens fornavn.")
last_name = models.CharField(max_length=30, help_text="Indtast medarbejderens efternavn.")
subjects = models.ManyToManyField(Subject, related_name='employee', through='Evaluation')
Evaluation Model
class Evaluation(models.Model):
name = models.CharField(blank=True,max_length=50)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE)
subject = models.ForeignKey('Subject', on_delete=models.CASCADE)
So the assumption, is an employee can have different subjects and the mapping is defined via a through model using many-to-many.
Your DetaiView can then just be
class EmployeeDetailView(DetailView):
template_name = 'evalsys/employee/alle_employees_eval.html'
model = Employee
def get_context_data(self, **kwargs):
context = super(EmployeeDetailViewDetailView,
self).get_context_data(**kwargs)
context['evaluations'] = Evaluation.objects.filter(employee=self.object)
return context
Template
{% for evaluation in evaluations %}
{{ evaluation.subject.subject_name }}
<p>{{ evaluation.name }} | {{ evaluation.employee.first_name }} |
{{evaluation.employee.last_name }}</p>
{% empty %}
<p>No evaluations founds.</p>
{% endfor %}

Problem with set value in view and template

I want to create a list where the user can give titles to his list in which he selects in which category he should be, this is how the model looks like
class UserListAnime(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
anime = models.ManyToManyField(Anime, through='ListAnime')
class Anime(models.Model):
title = models.CharField(max_length=200)
slug = extension_fields.AutoSlugField(populate_from='title', blank=True)
class ListAnime(models.Model):
LIST_CHOICES = (
(WATCHING, 'Oglądam'),
(PLANNING, 'Planuję'),
(COMPLETED, 'Ukończone'),
(DROPPED, 'Porzucone'),
(ONHOLD, 'Wstrzymane'),
(MISSING, 'Pomijam'),
)
user = models.ForeignKey(UserListAnime, on_delete=models.CASCADE, null=True, blank=True)
anime = models.ForeignKey(Anime, on_delete=models.CASCADE, null=True, blank=True)
type = models.CharField(max_length=30, choices=LIST_CHOICES, null=False, blank=False)
In the view I only have to take a list of the user and I have displayed it but I want it to be filtered through the type in ListAnime
def ListAnimeView(request, pk, username):
list_anime = UserListAnime.objects.filter(user__pk=pk, user__username=username,
listanime__type='ogladam',
anime__listanime__type='ogladam').all()
context = locals()
and html looks like
{% for list in list_anime.anime.all %}
{{ list }}
{% endfor %}
My question is how to extract all records when type = LIST_CHOICES and show this in html
EDIT: SOLVED just need change in view from UserListAnime,objects.. to ListAnime.objects
and in html should be
{% for list in list_anime %}
{{ list.anime }}
{% endfor %}
I don't know exactly what are you trying to achieve. Do you want to get a list of ListAnime entities given a user, and get only which are of type 'ogladam'?
def listAnimeView(request, pk):
list_anime = ListAnime.objects.filter(user__user_id=pk, type='ogladam')
return render(request, 'template-name', context=['list_anime': list_anime])'

django - can't filter object and transfer to template

I've got a model which I'm trying to filter according to an argument passed in the url, then display the filtered object via a template, but I don't know what I'm doing wrong.
Here's the urls.py:
url(r'^courses/(?P<course_code>\w+)/$', views.course, name="course"),
Here's the view:
from website.models import Course
def course(request, course_code):
current_course = Course.objects.filter(short_title='course_code')
template = loader.get_template('website/course.html')
context = Context({
'current_course': current_course,
})
return HttpResponse(template.render(context))
Here's the model:
class Course(models.Model):
title = models.CharField(max_length=200)
short_title = models.CharField(max_length=5)
course_type = models.CharField(max_length=100)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
fee = models.IntegerField()
places = models.IntegerField()
venue = models.CharField(max_length=200)
description = models.TextField()
short_description = models.TextField()
age_low = models.IntegerField()
age_high = models.IntegerField()
And here's the template:
{% if current_course %}
{% for course in current_course %}
{{ current_course.title }}
{% endfor %}
{% else %}
<p>Sorry, that course doesn't exist.</p>
{% endif %}
And when I load the page /courses/CR1 (the course with short_title="CR1" definitely exists because it renders fine on another template where I'm not filtering but just displaying all the courses), it gives me "Sorry, that course doesn't exist."
Can anyone see what I'm doing wrong?
In this line:
current_course = Course.objects.filter(short_title='course_code')
You're checking for course titles with the exact text 'course_code'. You mean to use the value of the variable course_code:
current_course = Course.objects.filter(short_title=course_code)