Django Inner Join and Left Join Query - django-models

I am trying to slove the problem for Inner Join and Left Join in Django ORM.
My Models
class Student(models.Model):
ID = models.AutoField(primary_key=True)
Name = models.CharField(max_length=70, blank=False, default='')
Code = models.CharField(max_length=10, blank=False, default='')
Active = models.CharField(max_length=1)
def __str__(self):
return self.Name
class Teacher(models.Model):
ID = models.AutoField(primary_key=True)
Name = models.CharField(max_length=200)
StudentID = models.ForeignKey(Student, on_delete=models.CASCADE, null=True)
createdUser = models.CharField(max_length=50)
createdDate = models.DateTimeField()
UpdatedUser = models.CharField(max_length=50)
UpdatedDate = models.DateTimeField()
To_StudentId = models.CharField(max_length=50)
Subjects = models.CharField(max_length=50)
def __str__(self):
return self.Name
I was tried with below ORM Query but I am not getting Proper Result Set.
statusFiles = Teacher.objects.filter( 'To_StudentId').select_related('StudentID')
My SQL Native Query is below
SELECT T.Name, T.Code, T.createdDate AS ProcessDate,
ifnull(S1.Code,'All') As HomeTution, ifnull(S2.Code,'All') As TOTution,
if(Active = 1, 'Success', 'Failure') As Status,
FROM Teacher T
INNER JOIN Student S1 ON S1.ID=T.StudentID
LEFT JOIN Student S2 ON S2.ID=T.To_StudentId
where T.Subjects IN ('Maths','English') order by T.ID desc;
Could you please help me any one how to achievethis by using ORM Django.

Related

I want to Join two tables each related (by a ForeignKey) to a third one (but not each other)

The three models relevant to this question are:
class MaterialList(models.Model):
org = models.ForeignKey(Organizations, on_delete=models.RESTRICT, blank=True)
Material = models.CharField(max_length=100)
Description = models.CharField(max_length=250, blank=True)
PartType = models.ForeignKey(WhsePartTypes, null=True, on_delete=models.RESTRICT)
Price = models.FloatField(null=True, blank=True)
PriceUnit = models.PositiveIntegerField(null=True, blank=True)
TypicalContainerQty = models.IntegerField(null=True, blank=True)
TypicalPalletQty = models.IntegerField(null=True, blank=True)
Notes = models.CharField(max_length=250, blank=True)
UniqueConstraint('org', 'Material')
class Meta:
ordering = ['org','Material']
class CountSchedule(models.Model):
org = models.ForeignKey(Organizations, on_delete=models.RESTRICT, blank=True)
CountDate = models.DateField(null=False)
Material = models.ForeignKey(MaterialList, on_delete=models.RESTRICT)
Counter = models.CharField(max_length=250, blank=True)
Priority = models.CharField(max_length=50, blank=True)
ReasonScheduled = models.CharField(max_length=250, blank=True)
Notes = models.CharField(max_length=250, blank=True)
UniqueConstraint('org', 'CountDate', 'Material')
class Meta:
ordering = ['org','CountDate', 'Material']
class ActualCounts(models.Model):
org = models.ForeignKey(Organizations, on_delete=models.RESTRICT, blank=False)
CountDate = models.DateField(null=False)
CycCtID = models.CharField(max_length=100, blank=True)
Material = models.ForeignKey(MaterialList, on_delete=models.RESTRICT)
Counter = models.CharField(max_length=250, blank=False, null=False)
LocationOnly = models.BooleanField(blank=True, default=False)
CTD_QTY_Expr = models.CharField(max_length=500, blank=False)
BLDG = models.CharField(max_length=100, blank=True)
LOCATION = models.CharField(max_length=250, blank=True)
PKGID_Desc = models.CharField(max_length=250, blank=True)
TAGQTY = models.CharField(max_length=250, blank=True)
FLAG_PossiblyNotRecieved = models.BooleanField(blank=True, default=False)
FLAG_MovementDuringCount = models.BooleanField(blank=True, default=False)
Notes = models.CharField(max_length = 250, blank=True)
class Meta:
ordering = ['org', 'CountDate', 'Material']
These models arise from a migration from a non-Python system to a Python-Django driven system. Most of the time, I only need the forward relations CountSchedule.Material and ActualCounts.Material. There is one report my bosses L_O_V_E, however. This report joins ActualCounts and CountSchedule where ActualCounts.CountDate=CountSchedule.CountDate and ActualCounts.Material=CountSchedule.Material. (Actually, the report has 3 sections, which boil down to a LEFT JOIN, a RIGHT JOIN and an INNER JOIN. For now, I just need help with any of these as a start).
For the moment, I'm going with raw SQL, but I'd like to know if the ORM has a solution.
Any advice?
I've already tried
M = MaterialList.objects.select_related('actualcounts_set', 'countschedule_set').filter(org=_userorg, actualcounts__CountDate=datestr, countschedule__CountDate=datestr)
which resulted in
Invalid field name(s) given in select_related: 'countschedule_set', 'actualcounts_set'. Choices are: org, PartType

How can I use an if condition in model.py Django?

I would like if a student studies "Computer Science", for example, that in the "Categories" class he can only select certain "Categories". Unfortunately I get the following error:
ERRORS:
accounds.Categories.members: (fields.E305) Reverse query name for 'accounds.Categories.members' clashes with reverse query name for 'accounds.Categories.members_ptr'.
HINT: Add or change a related_name argument to the definition for 'accounds.Categories.members' or 'accounds.Categories.members_ptr'.
from django.db import models
from datetime import date
# Create your models here.
class Members(models.Model):
created_at = models.DateField(default=date.today, null=True)
vorname = models.CharField(max_length=200, null=True)
nachname = models.CharField(max_length=200, null=True)
Studiengang = (("IT & Technik","IT & Technik") ,("Designs & Medie", "Designs & Medie"),
("Personal & Recht","Personal & Recht"), ("Informatik","Informatik"))
studiengang = models.CharField(max_length=200, null=True, choices=Studiengang)
email = models.CharField(max_length=200, null=True)
passwort = models.CharField(max_length=200, null=True)
def __str__(self):
return self.vorname
class Categories(Members):
if Members.studiengang == "Informatik":
Kategorien = (
("Mathematik Grundlagen I", "Mathematik Grundlagen I"),
("Grundlagen der industriellen Softwaretechnik", "Grundlagen der industriellen
Softwaretechnik"),
)
kategorien = models.CharField(max_length=200, null=True, choices=Kategorien)
members = models.ForeignKey(Members, null=True,on_delete= models.SET_NULL)
class Statistik(models.Model):
fragen_insgesammt = models.IntegerField(null=True)
fragen_richtig_beantwortet = models.IntegerField(null=True)
fragen_falsch_beantwortet = models.IntegerField(null=True)
anzahl_der_punkte = models.IntegerField(null=True)
student = models.ForeignKey(Members, null=True,on_delete= models.SET_NULL)
I would be super happy if someone could help
in Categories Model > members ForeignKey add argument (related_name)
members = models.ForeignKey(Members, null=True,on_delete= models.SET_NULL,related_name="members_list")

How do i access another column from related table other than the foreign key, when creating an API view

Im using django for a web app and i am creating REST API views. Is there a way i can access two tables in one view? If not, how can can i retrieve a non-foreign key column from a related record. The below code is retrieving a vase record based on a URL parameter. I want to access the artistName which is stored in artist table (a one-to-many with Vase table), not artist_id which is stored in Vase
class FilterVases(generics.ListAPIView):
serializer_class = VaseSerializer
def get_queryset(self):
queryset = Vase.objects.all()
artist_id = self.request.query_params.get('artist_id')
if artist_id is not None:
queryset = queryset.filter(artist_id=artist_id)
vaseID = self.request.query_params.get('vaseID')
if vaseID is not None:
queryset = queryset.filter(vaseID=vaseID)
return queryset
edited to add
This is models for Artist and Vase:
class Artist(models.Model) :
artistID = models.CharField(max_length=10)
artistName = models.CharField(max_length=100)
class Vase(models.Model):
vaseID = models.CharField(max_length=10)
vaseRef = models.CharField(max_length=255,blank=True,null=True)
inscription = models.CharField(max_length=255,blank=True,null=True)
fabric = models.CharField(max_length=100, blank=True,null=True)
subject = models.CharField(max_length=255,blank=True,null=True)
technique = models.CharField(max_length=100,blank=True,null=True)
height = models.FloatField(max_length=100,blank=True,null=True)
diameter = models.FloatField(max_length=100,blank=True,null=True)
shape = models.ForeignKey(Shape, on_delete=models.CASCADE)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
provenance = models.ForeignKey(Provenance, on_delete=models.CASCADE)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
In the Vase model add this:
def artist_name(self):
return self.artist.artistName
Hence, it will look like:
class Vase(models.Model):
vaseID = models.CharField(max_length=10)
vaseRef = models.CharField(max_length=255,blank=True,null=True)
inscription = models.CharField(max_length=255,blank=True,null=True)
fabric = models.CharField(max_length=100, blank=True,null=True)
subject = models.CharField(max_length=255,blank=True,null=True)
technique = models.CharField(max_length=100,blank=True,null=True)
height = models.FloatField(max_length=100,blank=True,null=True)
diameter = models.FloatField(max_length=100,blank=True,null=True)
shape = models.ForeignKey(Shape, on_delete=models.CASCADE)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
provenance = models.ForeignKey(Provenance, on_delete=models.CASCADE)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
def artist_name(self):
return self.artist.artistName
In the VaseSerializer add the 'artist_name' to the fields Meta.
If you want to add this custom fields to all Vase Model fields, refer to this topic Django Rest framework, how to include '__all__' fields and a related field in ModelSerializer ?
class VaseSerializer(serializers.ModelSerializer):
class Meta:
model = models.Vase
fields = '__all__'
extra_fields = ['artist_name']
def get_field_names(self, declared_fields, info):
expanded_fields = super(VaseSerializer, self).get_field_names(
declared_fields, info)
if getattr(self.Meta, 'extra_fields', None):
return expanded_fields + self.Meta.extra_fields
else:
return expanded_fields
Below should your view:
class FilterVases(generics.ListAPIView):
serializer_class = VaseSerializer
def get_queryset(self):
queryset = Vase.objects.all()
query_artist = self.request.query_params.get('artist_name')
if query_artist is not None:
try:
artist = Artist.objects.get(artistName=query_artist)
queryset = queryset.filter(artist=artist)
except:
pass
vaseID = self.request.query_params.get('vaseID')
if vaseID is not None:
queryset = queryset.filter(vaseID=vaseID)
return queryset

How can i add custom fields to ModelSerializer?

i have a PurchaseDetail model like
class PurchaseDetail(NowTimestampAndUserModel):
purchase = models.ForeignKey(PurchaseMaster, default=False, related_name="purchase_details", on_delete=models.CASCADE)
item = models.ForeignKey(Item, default=False, on_delete=models.CASCADE)
item_category = models.ForeignKey(ItemCategory, default=False, on_delete=models.CASCADE)
purchase_cost = models.DecimalField(max_digits=19, decimal_places=2, default=0.0)
sale_cost = models.DecimalField(max_digits=19, decimal_places=2, default=0.0)
qty = models.FloatField(help_text="Purchase quantity")
ref_purchase_order_detail = models.PositiveIntegerField(default=0)
ref_purchase_detail = models.PositiveIntegerField(default=0)
and i have "Item" model and "item_category" models as
ITEM
class ItemCategory(NowTimestampAndUserModel):
name = models.CharField(max_length=50, unique=True, help_text="Category name should be max. of 50 characters")
code = models.CharField(max_length=10, unique=True, help_text="Province name should be max. of 10 characters")
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
ITEM_CATEGORY
class ItemCategoryHist(NowTimestampAndUserModel):
name = models.CharField(max_length=50, help_text="Category name should be max. of 50 characters")
code = models.CharField(max_length=10, help_text="Province name should be max. of 10 characters")
def __str__(self):
return self.name
i want to make serializer class as
class StockSerializer(serializers.ModelSerializer):
item_name = Field(source='get_item_name')
class Meta:
model = PurchaseDetail
# some fields of PurchaseDetail
fields = ['id', 'item_name ', 'item_category']
def get_item_name(self, obj):
item_id = obj.item
item_obj = Item.objects.get(pk=item_id)
name = item_obj.name
return name
I want to serialize item name field only with Purchase Detai. How ca i do it?
What you need are Serializer Method Fields: https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
The field "item_name" can be a SerializerMethodField, allowing you to have custom code to generate the value for that field.

How can I access my models in django admin?

I am working on an AlumniTracker in django and till now I have created forms for user sign up and some additional information.
Even after saving the additional information form I am not able to access it in django-admin.
I am adding my models, views and forms file here.
views.py
def student_profile(request):
if request.method == 'POST':
form = StudentDetailForm(request.POST)
if form.is_valid:
student_form = form.save(commit=False)
student_form.user = request.user
student_form.save()
return redirect(reverse('homepage'))
else:
form = StudentDetailForm()
return render(request, 'authentication/student_profile.html', {'form':form})
def alumni_profile(request):
if request.method == 'POST':
form = AlumniDetailForm(request.POST)
if form.is_valid:
alumni_form = form.save(commit=False)
alumni_form.user = request.user
alumni_form.save()
return redirect(reverse('homepage'))
else:
form = AlumniDetailForm()
return render(request, 'authentication/student_profile.html', {'form':form})
forms.py
class StudentDetailForm(ModelForm):
class Meta:
model = StudentDetail
fields = ['first_name', 'last_name', 'contact_no', 'birth_date', 'course', 'session_start', 'session_end']
class AlumniDetailForm(ModelForm):
class Meta:
model = AlumniDetail
exclude = ['user']
models.py
class CustomUser(AbstractUser):
profile = models.CharField(max_length=10,choices=PROFILE_CHOICES, default='student')
def __str__(self):
return self.username
class StudentDetail(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
contact_no = models.IntegerField()
birth_date = models.DateField()
course = models.CharField(max_length=50)
session_start = models.IntegerField()
session_end = models.IntegerField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class AlumniDetail(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
contact_no = models.IntegerField()
birth_date = models.DateField()
course = models.CharField(max_length=50)
session_start = models.IntegerField()
session_end = models.IntegerField()
company = models.CharField(max_length=60)
open and edit admin.py
and register your models by adding code below admin import
from .models import CustomUser,StudentDetail,AlumniDetail
admin.site.register(CustomUser)
admin.site.register(StudentDetail)
admin.site.register(AlumniDetail)

Resources