I'm trying to query fields from another model in Django .
I'm able to fetch the user information using the following method
def student(self, *args, **kwargs):
std_name = Attendance.objects.get(roll=self.roll)
return std_name.name
Now I need to find the student's assigned teacher from a different table, I need to fetch it only using the student name which I got using student() as I don't have any variable in my current table to reference it to fetch that information from the new table.
def teacher(self, *args, **kwargs):
teacher_name = staff.objects.get(student=self.student)
return teacher_name.name
But the above method is not working properly and is not populating the fields in my admin.py page . Can someone help me in fixing this issue
#Attendance model
class Attendance(models.Model):
class Meta:
verbose_name = 'Attendance'
verbose_name_plural = ''Attendance''
Group = models.TextField(max_length=15, blank=True, null=True)
Year = models.IntegerField(blank=True,null=True)
roll = models.IntegerField(blank=True,null=True)
Date = models.TextField(max_length=15, blank=True, null=True)
name = models.TextField(max_length=10, blank=True, null=True)
Presence = models.TextField(max_length=15, blank=True, null=True)
def student(self, *args, **kwargs):
std_name = Attendance.objects.get(roll=self.roll)
return std_name.name
def teacher(self, *args, **kwargs):
teacher_name = staff.objects.get(student=self.student)
return teacher_name.name
#staff model
class staff(models.Model):
class Meta:
verbose_name = staff
verbose_name_plural = ''staff''
name = models.TextField(max_length=10, blank=True, null=True)
degree = models.TextField(max_length=15, blank=True, null=True)
subject = models.IntegerField(blank=True,null=True)
experience = models.IntegerField(blank=True,null=True)
student = models.TextField(max_length=15, blank=True, null=True)
Related
I have a class named Property with a field property_type, i wana autofill this field when i create one of the other models who have onetoone relationship with Property
I want the when i create a Apartment in django admin for exp the property_type in Property should autofill with the "Apartment", when i create Villa in django admin it should autofill with "villa"
class Property(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="agent_of_property")
district_id = models.ForeignKey(District, on_delete=models.CASCADE)
slug = models.SlugField(max_length=255, unique=True)
property_type = models.CharField(choices=PROPERTY_TYPE, max_length=20)
title = models.TextField(verbose_name="Titulli", help_text="Vendos titullin e njoftimit", max_length=500)
description = models.TextField(verbose_name="Pershkrimi", help_text="Vendos pershkrimin",max_length=1000)
address_line = models.CharField(verbose_name="Adresa", help_text="E nevojeshme",max_length=255)
price = models.IntegerField()
area = models.IntegerField()
views = models.IntegerField(default=0)
documents = models.CharField(verbose_name="Dokumentacioni", help_text="Dokumentat", max_length=255)
status = models.BooleanField(default=True)
activity = models.CharField(max_length=20, choices=ACTION_OPTION)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "Prona"
verbose_name_plural = "Pronat"
def get_absolute_url(self):
return reverse("pronat:property_detail", args=[self.slug])
def __str__(self):
return self.title
class Apartment(Property):
property_id = models.OneToOneField(Property, on_delete=models.CASCADE, parent_link=True, primary_key=True)
floor = models.IntegerField(default=0)
room_num = models.IntegerField(default=0)
bath_num = models.IntegerField(default=0)
balcony_num = models.IntegerField(default=0)
class Meta:
verbose_name = "Apartament"
verbose_name_plural = "Apartamentet"
def save(self, *args, **kwargs):
self.property_type = "Apartment"
class Villa(Property):
property_id = models.OneToOneField(Property, on_delete=models.CASCADE, parent_link=True, primary_key=True)
living_room = models.IntegerField(default=1)
floors = models.IntegerField(default=1)
room_num = models.IntegerField(default=1)
bath_num = models.IntegerField(default=1)
balcony_num = models.IntegerField(default=0)
class Meta:
verbose_name = "Vila"
verbose_name_plural = "Vilat"```
I don't understand what your are doing. If you are inheriting from Property models in Apartment just remove OneToOneField and your save method would be
def save(self, *args, **kwargs):
self.property_type = 'Apartment'
super().save(*args, **kwargs)
But if you really want to use OneToOneField, replace Property inherit with models.Model and your save method should look like this.
def save(self, *args, **kwargs):
self.property_id.property_type = 'Apartment'
self.property_id.save()
super().save(*args, **kwargs)
For 2nd case you can also use django signal
from django.db.models.signal import post_save
# ...
def populate_property_type(sender, created, instance, **kwargs):
if sender.__name__ == 'Apartment':
instance.property_id.property_type = 'Apartment'
instance.property_id.save()
# condition for Villa
post_save.connect(populate_property_type, sender=Apartment)
post_save.connect(populate_property_type, sender=Villa)
I would suggest that you should add field in Appartment table with the name appartment_type and remove property_type from Property. But If you don't want to do that then Two ways are possible for your case.
1.When you are adding values from Django admin, you should also add the property_type from Admin.In that case you don't need to override save method.
Register your Property and Appartment Table in one view.
Make the admin Tables of Property and Appartment for admin view. Then register it like this way i-e
admin.site.register(PropertyAdmin, AppartmentAdmin)
and add values into both tables.
2: Simply override the save method and add this
def save(self, *args, **kwargs):
self.property_id.property_type = 'Apartment' # you should add other field in Appartment table just avoid hard coded 'Apartment'
self.property_id.save()
super().save(*args, **kwargs)
First of all pardon me for my poor English. I'm using django-import-export to upload excel file into my student model that has foreign key relationship with university model
student.. models.py:
class Student(models.Model):
institution = models.ForeignKey(University, on_delete=models.CASCADE)
id = models.CharField(max_length=200, primary_key=True)
first_name = models.CharField(max_length=200)
middle_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
age = models.IntegerField()
faculty = models.CharField( max_length=200, null=True, blank=True)
program = models.CharField( max_length=200, null=True, blank=True)
def __str__(self):
return self.first_name
university.. models.py:
class University(models.Model):
name = models.CharField(max_length=300)
email = models.EmailField(max_length=255, unique=True)
phone_no1 = PhoneNumberField()
phone_no2 = PhoneNumberField(blank=True)
fax_no = PhoneNumberField()
website = models.URLField(max_length=200)
pob = models.IntegerField()
city = models.CharField(max_length=200, blank=True)
logo = models.ImageField(upload_to="logos/", blank=True, null=True)
def __str__(self):
return self.name
After reading django-import-export documentation about ForeignKeyWidget
I edited my resources.py file as following and it works fine when I upload excel file that contain institution id and other student information
resources.py
class StudentResource(resources.ModelResource):
institution = fields.Field(
column_name='institution',
attribute ='institution',
widget = ForeignKeyWidget(University, 'id')
)
class Meta:
model=Student
But I don't want to include institution id into my excel file while I am uploading, because I can find the institution id from Registrar Staff logged in since the RegistrarStaff model has foreign key relationship with university model
class RegistrarStaff(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, primary_key = True)
university = models.ForeignKey(University, on_delete=models.CASCADE, null=True)
phone_number = models.CharField(max_length=20)
def __str__(self):
return str(self.user)
This is the way I able to find institution id based on whose university Registrar Staff is logged in and passed the value into resource like on number 4 in views.py
views.py:
def upload(request):
if request.method == 'POST':
loged=request.user.id
univ = RegistrarStaff.objects.get(pk=loged).university_id
student_resource = StudentResource(institution=univ)
dataset = Dataset()
new_student = request.FILES['myfile']
if not new_student.name.endswith('xlsx'):
messages.info(request,'Wrong format')
return render(request, 'upload.html')
imported_data = dataset.load(new_student.read(), format='xlsx')
for data in imported_data:
value = Student(
data[0],
data[1],
data[2],
data[3],
data[4],
data[5],
)
value.save()
return render(request, 'upload.html')
And I intialized it in resources.py as follow
resources.py:
class StudentResource(resources.ModelResource):
def __init__(self, *args, **kwargs):
self._institution=kwargs.pop('institution', None)
super().__init__(*args, **kwargs)
print(self._institution)
class Meta:
model=Student
So, is there anyway I can set the value of institution id = self._institution so as to able to upload excel file that doesn't contain institution id????
You are on the right lines. The way to do this is to pass the institution instance (or id) into the constructor, which is what you have already. All you need to do is to set the institution instance onto the Student model instance before it is saved:
class StudentResource(resources.ModelResource):
def __init__(self, *args, **kwargs):
self._institution=kwargs.pop('institution', None)
super().__init__(*args, **kwargs)
print(self._institution)
def before_save_instance(self, instance, using_transactions, dry_run):
setattr(instance, "institution", self._institution)
class Meta:
model=Student
However, you are bypassing the django-import-export framework by calling Student.save() directly. Don't do this. Use the framework to handle instance creation for you (docs):
result = student_resource.import_data(imported_data, dry_run=True)
I've multiple models in my Django project but only this given below model creating another instance on update instead of save. This is happening in Django's Admin panel, not on my custom UI. When I remove my save() method then it works fine but this way I won't be able to create slug.
Does anybody know what I'm doing wrong in here
class Course(models.Model):
title = models.CharField(max_length=200)
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='category')
slug = models.SlugField(max_length=200, unique=True, primary_key=True, auto_created=False)
short_description = models.TextField(blank=False, max_length=60)
description = models.TextField(blank=False)
outcome = models.CharField(max_length=200)
requirements = models.CharField(max_length=200)
language = models.CharField(max_length=200)
price = models.FloatField(validators=[MinValueValidator(9.99)])
level = models.CharField(max_length=20)
application_link = models.URLField(max_length=1000, blank=True, null=True)
brochure = models.FileField(upload_to='brochures/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='thumbnails/')
video_url = models.CharField(max_length=100)
is_session_available = models.BooleanField(default=False)
session_url = models.CharField(max_length=250, default='')
is_published = models.BooleanField(default=True)
created_at = models.DateTimeField(default=now)
updated_at = models.DateTimeField(default=now)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Course, self).save(*args, **kwargs)
instead of overriding save method you could do this:
admin.py
class CourseAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Course, CourseAdmin)
It is happening because it will generate new slug every time. You can do something like this:
def generate_slug(self):
self.slug = slugify(self.name)
def save(self, *args, **kwargs):
if not self.slug:
self.generate_slug() # This will generate slug.
return super().save(*args, **kwargs)
class Source(models.Model):
Name = models.CharField(max_length=150)`enter code here`
Address = models.CharField(max_length=150)
Office_Phone = PhoneField(blank=True, help_text='Office phone number')
Main_Contact = models.CharField(max_length=150, blank=True, null=True)
Contact_Email = models.EmailField(max_length=254, blank=True, null=True)
Contact_Phone = PhoneField(blank=True, help_text='Main Contact phone number')
Billing_Contact = models.CharField(max_length=150, blank=True, null=True)
Billing_Email = models.EmailField(max_length=254, blank=True, null=True)
Billing_Phone = PhoneField(blank=True, help_text='Billing Contact phone number')
Notes = models.CharField(max_length=250, blank=True, null=True)
def __str__(self):
return self.Name
def get_absolute_url(self):
return reverse('sources-detail', kwargs={'pk': self.pk})
class Rate(models.Model):
Source = models.ForeignKey(Source, on_delete=models.CASCADE)
Report_Type = models.ForeignKey(ReportType, on_delete=models.CASCADE)
Amount = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = Rate.objects.all.filter(***not sure what to put here***)
return context
Would it be better to filter it in the Template or do it in the View? I am able to get results if I don't filter it and just use Rate.objects.all(), and then I filter it in my template. Just think there is a better way to do this.
You can just fetch the relation in reverse:
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = self.object.rate_set.all()
return context
That being said, here it does not make much difference to make the query in the template, since there is only one object here, so there is no N+1 problem.
i want to filter the many to many field in modelform.
class IdealBehaviour(models.Model):
cbs_role = models.ManyToManyField(CbsRole, null=True, blank=True)
cbs = models.ForeignKey('cbs.CBS', null=True, blank=True)
ideal_behaviour = models.CharField(max_length=500, null=True, blank=True)
Description = models.CharField(max_length=1000, null=True, blank=True)
created_time = models.DateTimeField(auto_now_add = True,null=True, blank=True)
class StandardWork(models.Model):
cbs_and_role = models.ManyToManyField('userdata.CbsRole', null=True, blank=True)
standard_work_number = models.BigIntegerField(null=True, blank=True)
system_name= models.CharField(max_length=500, null=True, blank=True)
system_description=models.TextField(null=True, blank=True)
ideal_behaviour = models.ManyToManyField ('userdata.IdealBehaviour', null=True, blank=True)
publish = models.BooleanField(default=False)
created_time = models.DateTimeField(auto_now_add = True,null=True, blank=True)
class TodoListForm(ModelForm): # used in manage view
class Meta:
model = StandardWork
exclude = ('publish', 'cbs_and_role', 'standard_work_number')
widgets = {
'system_description': forms.Textarea(attrs={'rows':3}),
}
i want to display the choices of ideal_behaviour for the query
cbsobject = CBS.objects.get(id=dat)
idealbehaviour = IdealBehaviour.objects.filter(cbs=cbsobject)
I want to choices for ideal_behaviour in TodoListForm as idealbehaviour only.
How can i query to display ideal-behaviour assosciated with that perticuler cbs only in modelform?
i got the solution
def __init__(self, *args, **kwargs):
super(PollForm, self).__init__(*args, **kwargs)
if self.instance:
print "printing in form"
print self.instance.id
self.fields['ideal_behaviour'].queryset = IdealBehaviour.objects.filter(cbs__exact=self.instance.id)
but i dont how to get the id for cbs. self.instance.id its giving for standardwork id. i want id for cbs. i.e cbsobject i want in form as a instance. after that its working fine.
Got the solution.
I don't know if it is feasible or not, but I put the forms in the views file only so I can get the instance for "cbsobject".
class PollForm(forms.ModelForm): # used in manage view
class Meta:
model = StandardWork
exclude = ('cbs_and_role','publish', 'standard_work_number')
widgets = {
'system_description': forms.Textarea(attrs={'rows':3}),
}
def __init__(self, *args, **kwargs):
super(PollForm, self).__init__(*args, **kwargs)
if self.instance:
print "printing in form"
print self.instance.id
self.fields['ideal_behaviour'].queryset = IdealBehaviour.objects.filter(cbs__exact=cbsobject)