Exclude entire QuerySet from results - django

I have the following models:
class LibraryEntry(models.Model):
player = models.ForeignKey(Player)
player_lib_song_id = models.IntegerField()
title = models.CharField(max_length=200)
artist = models.CharField(max_length=200)
album = models.CharField(max_length=200)
track = models.IntegerField()
genre = models.CharField(max_length=50)
duration = models.IntegerField()
is_deleted = models.BooleanField(default=False)
class Meta:
unique_together = ("player", "player_lib_song_id")
def __unicode__(self):
return "Library Entry " + str(self.player_lib_song_id) + ": " + self.title
class BannedSong(models.Model):
lib_entry = models.ForeignKey(LibraryEntry)
def __unicode__(self):
return "Banned Library Entry " + str(self.lib_entry.title)
I'd like to do a query like this:
banned_songs = BannedSong.objects.filter(lib_entry__player=activePlayer)
available_songs = LibraryEntry.objects.filter(player=activePlayer).exclude(banned_songs)
Basically if a song is banned, I want to exclude it from my set of available songs. Is there a way to do this in Django?

banned_song_ids = (BannedSong.objects.filter(lib_entry__player=activePlayer)
.values_list('lib_entry', flat=True))
available_songs = (LibraryEntry.objects.filter(player=activePlayer)
.exclude('id__in' = banned_song_ids))
The alternative is:
available_songs = (LibraryEntry.objects.filter(player=activePlayer)
.filter(bannedsong__isnull = True))

Related

Django custom queryset returns nothing

I am trying to write a year level filter for my student profile list, however, the query returns an empty [].
This is my Attendance model, manager and custom queryset:
class AttendanceQuerySet(models.QuerySet):
def get_yearlevel(self, yearlevel):
return self.filter(BCEID__YearLevel = yearlevel)
class AttendanceManager(models.Manager):
def get_queryset(self):
return AttendanceQuerySet(self.model, using=self._db)
def get_yearlevel(self, yearlevel):
return self.get_queryset().get_yearlevel(yearlevel)
class Attendance(models.Model):
BCEID = models.OneToOneField(StudentProfile,primary_key=True,on_delete=models.CASCADE)
AttendanceRate = models.CharField(max_length=10)
objects = AttendanceManager()
def __unicode__(self):
return self.BCEID
StudentProfile model:
class StudentProfile(models.Model):
RelatedPersonName = models.CharField(max_length=10)
RelatedPersonFirstName = models.CharField(max_length=30)
RelatedPersonFamName = models.CharField(max_length=30)
StudentLegalName = models.CharField(max_length=30)
StudentFamName = models.CharField(max_length=30)
Email = models.CharField(max_length=130)
Street1 = models.TextField(max_length=30)
Suburb = models.CharField(max_length=30)
State = models.CharField(max_length=5)
PostCode = models.CharField(max_length=6)
StudentLegalName = models.CharField(max_length=30)
StudentFamName = models.CharField(max_length=30)
StudentNo = models.CharField(primary_key=True,max_length=10)
Class = models.CharField(max_length=6)
YearLevel = models.CharField(max_length=10)
objects = StudentProfileManager()
def __unicode__(self):
return self.StudentNo
and AttendanceListView (views.py)
class AttendanceListView(ListView):
model = Attendance
queryset = Attendance.objects.get_yearlevel("Year 8")
I manually queried the database to check if there were errors in my code, and got the same result: an empty array [].
SQL:
SELECT "student_attendance"."BCEID_id",
"student_attendance"."AttendanceRate"
FROM "student_attendance"
INNER JOIN "student_studentprofile"
ON ("student_attendance"."BCEID_id" = "student_studentprofile"."StudentNo")
WHERE "student_studentprofile"."YearLevel" = 'Year 8'
Please let me know what I am doing wrong here.

How can I filter manytomany models?

I would like to filter my plots objects on the fruit ex.pear. The Inputs are linked via a manytomany to the plots. This is the structure:
This is the data I get out of it:
What i would like to have:
result:
I tried the following:
plots = Plot.objects.filter(fruittype__fruit="Pear")
inputs = Input.objects.filter(plot__in=plots).distinct()
This gives me already a close solution for my problem but not what I want.
Now I only would like to filter out the other plots that still show up with apple.
models inputs:
class Product (models.Model):
type = models.ForeignKey(Type, on_delete=models.CASCADE)
product = models.CharField(max_length=70)
standaard_dosis = models.FloatField()
def __str__(self):
return self.product
class Input (models.Model):
datum = models.DateField()
plot = models.ManyToManyField(Plot)
def __str__(self):
return str(self.datum)
class ProductInputs (models.Model):
input = models.ForeignKey(Inputs, on_delete=models.CASCADE, default="")
product = models.ForeignKey(Product, on_delete=models.CASCADE, default="")
dosis = models.FloatField()
def __str__(self):
string = str(self.product)
return string
models plots:
class Fruit(models.Model):
fruit = models.CharField(max_length=30, primary_key=True)
def __str__(self):
return self.fruit
class Meta:
verbose_name_plural = "fruits"
class Fruittype(models.Model):
fruit = models.ForeignKey(Fruit, on_delete=models.CASCADE)
fruittype = models.CharField(max_length=30, primary_key=True)
def __str__(self):
return self.fruittype
class Meta:
verbose_name_plural = "fruitypes"
class Plot(models.Model):
name = models.CharField(max_length=30)
fruittype = models.ForeignKey(Fruittype, on_delete=models.CASCADE)
def __str__(self):
return str(self.fruittype.fruit) + " | " + self.name
class Meta:
verbose_name_plural = "plots"
Your Plot queryset is not going as deep as it should. I think you should change to something like this (although this is it's a bit of overkill)
plot_ids = Plot.objects.filter(fruittype__fruit__fruit="Pear").values_list('pk', flat=True)
or
plot_ids = Plot.objects.filter(fruittype__fruittype="Pear").values_list('pk', flat=True) # I don't know what fruittype is but I guess this would help you
Then your "inputs"
inputs = Input.objects.filter(plot__pk__in=plot_ids).distinct()
You might wanna try this as well:
from django.db.models import Prefetch
Input.objects.prefetch_related(
Prefetch('plot', queryset=Plot.objects.filter(fruittype__fruit__fruit="Pear"))
)
It worked with:
all_inputs=Input.objects.filter(plot__pk__in=plot_ids).distinct().prefetch_related(Prefetch('plot', queryset=Plot.objects.filter(fruittype__fruit__fruit="Pear")))

Modify database in django

I am a beginner in django. Following is my Attendance Management App.
This is my models.py.
from django.db import models
class Subject(models.Model):
subject_name = models.CharField(max_length=20)
#attendance = models.ForeignKey(Attendance, on_delete =
models.DO_NOTHING)
attendance = models.IntegerField(default=0)
def __str__(self):
return self.subject_name
class Section(models.Model):
section_name = models.CharField(max_length=20)
subject = models.ManyToManyField(Subject)
def __str__(self):
return self.section_name
class Student(models.Model):
rollno = models.IntegerField()
name = models.CharField(max_length=20)
section = models.ForeignKey(Section, on_delete = models.DO_NOTHING,
default=0)
def __str__(self):
return str(self.rollno) + self.name
class Teacher(models.Model):
#teacher_name = models.CharField(max_length=20)
section = models.ForeignKey(Section, on_delete=models.CASCADE)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
#section_name = models.CharField(max_length=10)
#subject_name = models.CharField(max_length=30)
def __str__(self):
return self.section.section_name+' '+self.subject.subject_name
class TeacherList(models.Model):
teacher_name = models.CharField(max_length=20)
teacher = models.ManyToManyField(Teacher)
def __str__(self):
return self.teacher_name
The line below is not working in views.py
student = models.Student.objects.get(rollno = sroll)
student.section.subject.get(subject_name = 'java').attendance += 1
student.save()
This view is called from a template when a button is clicked to add attendance of a student.
The attendance in above code is not modified. Please help me out.
You're saving the student, instead of the subject.
student = models.Student.objects.get(rollno = sroll)
subject = student.section.subject.get(subject_name='java')
subject.attendance += 1
subject.save()
Or, better, do the update directly in one go:
student.section.subject.filter(subject_name='java').update(attendance=F('attendance')+1)
and there's no need to save at all.

manytomanyfield distinct value

i have a model called mti(Material Information) which have a list of MTD(Material Description) and in each material description description there is a size and color
i have an MTI id i want to get all the distinct list of color values
mymti = mti.objects.get(pk=1)
how can i get the list of colors from MTI
mymti.mtd.color.name ?
class color(models.Model):
id = models.AutoField(primary_key=True)
name= models.CharField(max_length=255)
stamp= models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.name
class mtd(models.Model):
id = models.AutoField(primary_key=True)
barcode = models.CharField(max_length=255)
#mti = models.ManyToManyField(mti)
size = models.ForeignKey(size)
color = models.ForeignKey(color)
weight = models.FloatField()
def __unicode__(self):
return u'%s - %s %s' % (self.barcode,self.color.name,self.size.name)
class Meta:
verbose_name = "MTD"
verbose_name_plural = verbose_name
class mti(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
item = models.ForeignKey(item)
mtd= models.ManyToManyField(mtd)
country = models.ForeignKey(country)
dept = models.ForeignKey(dept)
fabric = models.ForeignKey(fabric)
sesason = models.ForeignKey(season)
sale = models.FloatField()
endUser = models.FloatField()
description = models.TextField(max_length=1000,blank=True,null=True)
year = models.CharField(max_length=255,default=strftime("%Y", gmtime()))
front_page = models.BooleanField(verbose_name="Front Page",default=True)
active = models.BooleanField(default=True)
stamp = models.DateTimeField(auto_now=True)
def __unicode__(self):
return u'%s - %s' % (self.name, self.description)
class Meta:
verbose_name = "MTI"
verbose_name_plural = verbose_name
class mtiimage(models.Model):
id = models.AutoField(primary_key=True)
mtd = models.ManyToManyField(mtd)
image1 = models.ImageField(verbose_name="Product 1 Image",upload_to='product')
image2 = models.ImageField(verbose_name="Product 2 Image",upload_to='product')
image3 = models.ImageField(verbose_name="Product 3 Image",upload_to='product')
stamp = models.DateTimeField(auto_now=True)
def admin_thumbnail(self):
return u'<img src="%s" heigh="150" width="200" />' % (self.image1.url)
admin_thumbnail.short_description = 'Thumbnail'
admin_thumbnail.allow_tags = True
def __unicode__(self):
return u'%s ' % (self.id)
class Meta:
verbose_name = "MTI Image"
verbose_name_plural = verbose_name
Annotation
Use annotation.
mymti = mti.objects.get(pk=1)
unique_colors = mymti.mtd.values_list('color__name', flat=True).annotate()
colors = mymti.mtd.values_list('color__name', flat=True).distinct()
will result in :
colors = [color1, color2, ...]

Get Foreign Key Value

How can I get the foreign key values? I have a common vehicle model that links to the year, series, engine type, body style, transmission and drive train...all as foreign keys. I'd like to get the values of these fields for my app, but I'm stuck as to how I'd go about them. Any ideas will be highly appreciated.
class Model(models.Model):
model = models.CharField(max_length=15, blank=False)
manufacturer = models.ForeignKey(Manufacturer)
date_added = models.DateField()
def __unicode__(self):
name = ''+str(self.manufacturer)+" "+str(self.model)
return name
class Year(models.Model):
ALPHA_NUMERIC_CHOICES = (
('1', 'Numeric'),
('A', 'Alphabetic'),
)
year = models.PositiveSmallIntegerField()
position_7_char = models.CharField(max_length=1, choices=ALPHA_NUMERIC_CHOICES)
position_10 = models.CharField(max_length=1, blank=False)
def __unicode__(self):
return unicode(self.year)
class Series(models.Model):
series = models.CharField(max_length=20, blank=True)
model = models.ForeignKey(Model)
date_added = models.DateField()
def __unicode__(self):
name = str(self.model)+" "+str(self.series)
return name
class CommonVehicle(models.Model):
year = models.ForeignKey(Year)
series = models.ForeignKey(Series)
engine = models.ForeignKey(Engine)
body_style = models.ForeignKey(BodyStyle)
transmission = models.ForeignKey(Transmission)
drive_train = models.ForeignKey(DriveTrain)
def __unicode__(self):
name = ''+str(self.year)+" "+str(self.series)
return name
class Vehicle(models.Model):
stock_number = models.CharField(max_length=6, blank=False)
vin = models.CharField(max_length=17, blank=False)
common_vehicle = models.ForeignKey(CommonVehicle)
exterior_colour = models.ForeignKey(ExteriorColour)
interior_colour = models.ForeignKey(InteriorColour)
interior_type = models.ForeignKey(InteriorType)
odometer_unit = models.ForeignKey(OdometerUnit)
status = models.ForeignKey(Status)
odometer_reading = models.PositiveIntegerField()
selling_price = models.PositiveIntegerField()
purchase_date = models.DateField()
sales_description = models.CharField(max_length=60, blank=False)
def __unicode__(self):
return self.stock_numberodels.ForeignKey(CommonVehicle)
You need the actual IDs? Try something like my_vehicle_ref.series.id.
Also, I hope you know that the series attribute right there is really an instance of Series, so you could access any of it's properties, e.g., my_vehicle_ref.series.model.model.