Django - Select only specific rows from a query - django

I've started to learn django and as my first project I am trying to create a catalog.
I created 3 tables
Students
Catalog
Link table between those 2
This is how my models.py looks like:
class Catalog(models.Model):
Class = models.CharField(max_length =30)
def __str__(self):
return str(self.Class)
class StudentiAn4(models.Model):
Username = models.ForeignKey(User)
FirstName = models.CharField(max_length=50)
LastName = models.CharField(max_length=50)
Group = models.CharField(max_length=4)
def __str__(self):
return str(self.Username) + ' ' + self.FirstName +' ' + self.LastName
class CatalogStudenti(models.Model):
catalog = models.ForeignKey(Catalog)
student = models.ForeignKey(StudentiAn4)
grade = models.IntegerField()
def __str__(self):
return str(self.catalog) +' ' + str(self.student)
In views :
def studenti(request):
query = CatalogStudenti.objects.all()
return render(request, 'users/Studenti.html',{'query': query})
As a logged in user(Username: 123, FirstName: test1, LastName: test1_LN), I would like to see only grades assigned to me, not all grades.
Can you please tell me how can I filter the output so that I see only the grades assigned to me?
Current output:
123 test1 test1_LN - SEP 5
234 test2 test2_LN - ASC 4
123 test1 test1_LN - AACEP 6
Desired Output:
123 test1 test1_LN - SEP 5
123 test1 test1_LN - AACEP 6

Change the queryset in the view funtion to filter by the user field from student:
query = CatalogStudenti.objects.filter('student__Username'=request.user)

Related

List of arrivals, per year

I have these three models (I've summarize them):
class Tourist(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class Etablissement(models.Model):
name = models.CharField(max_length=30)
class Arrival(models.Model):
tourist = models.ForeignKey(Tourist, on_delete=models.CASCADE)
place = models.ForeignKey(Etablissement, on_delete=models.CASCADE)
I want, for a Tourist, to have all his arrivals, per year.
I've tried this:
def detailTourist(request, id):
touriste = Tourist.objects.get(id=id)
datas = Arrival.objects.annotate(year=TruncYear('arrival_date')).values('year').annotate(total=Arrival.objects.filter(tourist=touriste)).order_by()
but it give me an error: sub-select returns 19 columns - expected 1 (the arrival model has 19 field so i guest that's why it says 19.
So finnaly, how can I do it please ?
You can use itertools.groupby(…) [Python-doc] to group the items, given it is already ordered by year:
from itertools import groupby
from operator import attrgetter
def detailTourist(request, id):
datas = Arrival.objects.annotate(year=TruncYear('arrival_date')).order_by('year')
datas = { y: list(vs) for y, vs in groupby(datas, attrgetter('year')) }
# …
Here it will create a dictionary that maps a year to a list of Arrival objects.

demo application issue with models and queryset

I am trying to make one simple application but seems like facing issue. I have created many to many object between student and course and has also define dept.
My model is mentioned below:
class Course(models.Model):
courseId = models.AutoField(primary_key=True)
courseName = models.CharField(max_length=100)
enrolledStu = models.IntegerField(max_length=3)
students = models.ManyToManyField(Student)
dept = models.ForeignKey(Dept, on_delete=models.CASCADE)
def __str__(self):
return '%s %s %s %s' % (self.courseName,self.enrolledStu,self.students,self.dept)
class Dept(models.Model):
deptId = models.AutoField(primary_key=True)
deptName = models.CharField(max_length=100)
def __str__(self):
return '%s %s' % (self.deptId, self.deptName)
class Student(models.Model):
stuName = models.CharField(max_length=100)
stuCity = models.CharField(max_length=100)
stuPhone = models.IntegerField(max_length=10)
stuNationality = models.CharField(max_length=50)
stuCreatedt = models.DateTimeField(default=timezone.now)
def __str__(self):
return '%s %s %s' % (self.stuName,self.stuCity,self.stuNationality)
my form is :
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('stuName','stuCity','stuPhone','stuNationality','stuCreatedt')
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ('courseId','courseName','enrolledStu','students','dept')
class DeptForm(forms.ModelForm):
class Meta:
model = Dept
fields = ('deptId','deptName')
I have displayed list of course , students and dept in html template now i am trying to edit it with code :
def edtStudent(request,pk):
course = Course.objects.filter(pk=1).prefetch_related('students').select_related('dept').get()
if request.method =="POST":
form = CourseForm(request.POST,instance=Course)
if form.is_valid():
course = form.save(commit=False)
print(form.cleaned_data)
course.courseName = request.POST['courseName']
course.enrolledStu = request.Post['enrolledStu']
course.save()
course.save_m2m()
return redirect('liststudent')
else:
print(course.__dict__)
print(course.students)
#form = CourseForm()
#return render(request, 'stuApp/edtStudent.html', {'form':form})
#form = CourseForm(instance=course[0]) worked
form = CourseForm(instance=course)
return render_to_response('stuApp/edtStudent.html', {'form': form})
so instead of getting one student i am getting all students for course.. Seems like my query is incorrect. Can you help with that..
Another question i have is how can i print values for objects in many to many relationship.. for now if i print course object i am getting results like
{'_state': <django.db.models.base.ModelState object at 0x000000000457ED68>, 'courseId': 1, 'courseName': 'Account', 'enrolledStu': 1, 'dept_id': 1, '_dept_cache': <Dept: 1 Finance>, '_prefetched_objects_cache': {'students': <QuerySet [<Student: Mamta Mumbai Indian>]>}}
..
so from Query Set i would like to take only student name...
Jordan
I have follow up question for this.. when i try to edit course for html template it gets the values which are correct ,but for student its gets all attribute like studentname , city , natinality etc.. which wrong.. i want only student name from student and display it in template.
I am using following query to get course related information.
course = Course.objects.filter(pk=1).prefetch_related('students').select_related('dept').get()
getting results from query but for student it gets all attribute
Now in my views i am using this code:
course = Course.objects.filter(pk=1).prefetch_related('students').select_related('dept').get()
form = CourseForm(instance=course)
return render_to_response('stuApp/edtStudent.html', {'form': form})
i figured out how to get value for student name instead of all atributes.
course.students = course.students.value_list('stuName', flat=True)
but i am not sure how can i set above value to form and display it in template..
this where i am failing..

Query Values Muliple Field Foreign Key Column

This is my model:
class Personel(models.Model):
Numara = models.IntegerField(max_length=10)
Isim = models.CharField(max_length=30)
Soyisim = models.CharField(max_length=30)
class Islem(models.Model):
MenuAd = models.CharField(max_length=30)
Tarih = models.DateTimeField(auto_now_add=True)
Personel = models.ForeignKey(Personel)
Durum = models.PositiveIntegerField(max_length=5)
This is my query:
sorgu = Islem.objects.all().values('MenuAd', 'Personel')
sorgu result:
[{'MenuAd': 'Deneme', 'Personel': 2 }]
but, i want to result:
[{'MenuAd': 'Deneme', 'Personel': '2 - Baris Halici'}]
Numara: 2
Isim: Baris
Soyisim: Halici
example - proposal
def get_full_personel(self):
return "'%s - %s %s" % (self.Numara, self.Isim, self.Soyisim)
Thanks,
try changing your:
class Personel(models.Model):
def __unicode___(self):
return "'%s - %s %s" % (self.Numara, self.Isim, self.Soyisim)
or ___str___(self): if using python 3.
although that may not solve it... try:
sorgu = Islem.objects.all().values('MenuAd', 'Personel__get_full_personel')

Converting raw SQL to Django QuerySet API

Model
class Person(models.Model):
GENDER = (
('M','Male'),
('F','Female'),
)
first_name = models.CharField("First Name", max_length=100)
last_name = models.CharField("Last Name",max_length=100)
middle_name = models.CharField("Middle Name", max_length=100, blank=True)
suffix_name = models.ManyToManyField(SuffixName, verbose_name="Suffix Name",null=True, blank=True)
gender = models.CharField(max_length=1, choices=GENDER)
department = models.ManyToManyField(Department, verbose_name="Department",null=True, blank=True)
def __unicode__(self):
return (u'%s') % (self.last_name.upper() + ', ' + self.first_name + ' ' + self.middle_name)
class Department(models.Model):
department_desc = models.CharField('Department', max_length=100,unique=True)
department_acronym = models.CharField('Department Acronym', max_length=20,blank=True,help_text="Add acronym if any, not required")
location = models.CharField('Location',max_length=100,blank=True)
localnumber = models.CharField('Local Number',max_length=30,blank=True)
active = models.BooleanField('Active',default=True)
def __unicode__(self):
return self.department_desc
How can I convert this raw SQL to a Django query?
SELECT pp.first_name, pd.department_desc, pd.localnumber
FROM person_person as pp
INNER JOIN person_person_department as ppd on pp.id = ppd.person_id
INNER JOIN person_department as pd on pd.id = ppd.department_id
Use QuerySet.values or QuerySet.values_list:
Person.objects.values('first_name', 'department__department_desc', 'department__localnumber')
# -> Returns a ValuesQuerySet that yields dictionaries when iterated.
Person.objects.values_list('first_name', 'department__department_desc', 'department__localnumber')
# -> Returns a ValuesQuerySet that yields tuples when iterated.
Fetching on Person will automatically fetch the related objects, so your query is:
people = Person.objects.all()
Then, you can do the following:
for person in people:
print('Person: {0}'.format(person.first_name))
for dept in person.department_set.all():
print('Desc: {0}, Local Number: {1}'.format(dept.department_desc,
dept.localnumber))
If you want to restrict the returned values, use values_list.

how to write a method in order to change database directly in Django model

I made a Product class in Django models like :
class Product(models.Model):
title = models.CharField(max_length=255, unique = True)
description = models.TextField()
image_url = models.URLField(verify_exists=True, max_length=200, blank = True, null = True)
quantity = models.PositiveSmallIntegerField(default=0)
And i want to add a sell() method inside this class. well i did like:
def sell(self):
result = self.quantity - 1
return result
I want to change the value in database when just execute P.sell().
when i run it in the shell like this
>>p = Product(title = 'title', description = 'des', quantity = 10)
>>p.save()
>>p.sell()
9 # it shown 9, but the database not changed still 10
but if i continue to do like this
>> p.quantity = p.sell()
>> p.save()
it can change the quantity to 9
but how can i just change the value when i just type p.sell() ?
how could i edit it in models?
Uh...
def sell(self, save=True):
self.quantity -= 1
if save:
self.save()