Hello Django Pros out there!
Is it possible to get the pk of a model, which is not the direct foreign key of the model? But the foreignkey of the foreign key model?
My Models:
class Patient(models.Model):
patientID = models.CharField(max_length=200, unique=True, help_text='Insert PatientID')
class Examination(models.Model):
number_of_examination = models.IntegerField(choices=EXA_Choices)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
date_of_examination = models.DateField(auto_now=False, auto_now_add=False, help_text='YYYY-MM-DD')
class AbsoluteValue(models.Model):
examination = models.ForeignKey(Examination, on_delete=models.CASCADE)
attr1 = models.BooleanField(default=False)
attr2 = models.BooleanField(default=False)
attr3 = models.BooleanField(default=False)
and I want to define the get_absolute_url of the AbsoluteValue class. It should redirect to the Patient detail page. Due to this it needs the pk of the Patient class.
My try:
def get_absolute_url(self):
return reverse('member:detail', kwargs={'pk': self.examination__patient_id})
The error says that there is no URL to redirect to. So my query is not working, or I should not query in this function.
It looks like you want self.examination.patient_id instead of self.examination__patient_id. The double underscore notation is used by the Django ORM e.g. in filter(). For regular attribute access in Python, use a dot.
def get_absolute_url(self):
return reverse('member:detail', kwargs={'pk': self.examination.patient_id})
Related
Hi there Im trying to retrieve a specific object from the related model so as to render data to my view specific to that particular object, in my case I have a custom user model and a related model called Seller.
Models
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
is_customer = models.BooleanField(default=False)
is_seller = models.BooleanField(default=False)
class Seller(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
store_name = models.CharField(max_length=120)
address = models.CharField(max_length=180)
phone = models.IntegerField(blank=True, null=True)
email = models.CharField( max_length=180, blank=True, null=True )
def __str__(self):
return self.store_name
View
#method_decorator( seller_required , name='dispatch')
class SellerDashBoardView(ListView):
model = Seller
template_name = 'seller_dashboard.html'
def get_context_data(self, *args, **kwargs):
user = CustomUser.seller_set.filter(store_name=self.request.user.username)
context = super(SellerDashBoardView, self).get_context_data( **kwargs)
context['products'] = Product.objects.filter(seller=user)[:6]
return context
This is because when you want to filter ManyToOne reverse Relation, you have to make exact the same query as you would've been done with a direct relation:
CustomUser.objects.filter(seller__store_name="Whole Foods")
# Note that would return a queryset not a single user!
# If you want a CustomUser object you will have to use either get or index the query
The doc example and explanations are provided here:
https://docs.djangoproject.com/en/3.1/topics/db/examples/many_to_one/
It is also better to use prefetch_related method to tell djano ORM that it does not have to make as many queries as number of related objects, that query should be done in 2 database queries instead of lenght of your related query:
CustomUser.objects.prefetch_related("seller_set").filter(seller__store_name="Whole Foods")
The doc link:
https://docs.djangoproject.com/en/3.1/ref/models/querysets/#prefetch-related
You probably would like to use ...seller_set.filter when you already got a CustomUser object. So if you want to filter its sellers you would use that:
...
user.seller_set.filter(store_name="Whole Foods")
That would provide you the Seller objects queryset filtered by a store name related to a specific user. Basically the same query as this:
Seller.objects.filter(user_pk=user.pk, store_name="Whole Foods")
Below is my table :
class Project(models.Model):
name = models.CharField(max_length=100, null=False)
desc = models.CharField(max_length=100, null=False)
def __str__(self):
return self.name
class Activity(models.Model):
title = models.CharField(max_length=100, null=False)
project = models.ForeignKey(Project, on_delete=models.SET(some_func), null=False,
related_name='project_model')
So above is my table and when one of the datas of "project" table gets deleted then i want to assign "id or name" of the deleted "project" data to foreign key of the "activity" table.
How can i achieve this? pls help.
I assume you're doing this for logging purposes. I don't think using a ForeignKey field is a good option for storing an id that is not there anymore since the expected behavior of a ForeignKey is usually different than this.
But if you really need the id to be stored, I recommend using an IntegerField instead.
And to create a new Activity instance whenever a Project instance is deleted:
Overriding delete method:
class Project(models.Model):
name = models.CharField(max_length=100, null=False)
desc = models.CharField(max_length=100, null=False)
def delete(self, *args, **kwargs):
# create a new Activity
activity = Activity()
activity.title = self.name + " deleted!"
# if using ForeignKey field
activity.project = self
# if using IntegerField
activity.project = self.id
super(Project, self).delete(*args, **kwargs)
def __str__(self):
return self.name
Note: Set on_delete=DO_NOTHING if you're using a ForeignKey field so the instance won't be deleted. (It's not a good idea since it will cause integrity issues.)
I want to get a specific Video object and then find all of the Rating objects that are associated with it using ForeignKey reverse lookup as described in the docs.
I have models:
class Video(models.Model):
...
rating_int = models.IntegerField(default=1, choices=CHOICES, name='rating_int')
def __str__(self):
return self.title
class Rating(models.Model):
video = models.ForeignKey('Video', related_name='video', null=True)
and views:
def video_ratings(request):
vid_rate = Video.objects.get(pk=1)
ratings_of_video = vid_rate.rating_set.all()
context = {
'vid_rate': vid_rate, 'ratings_video': ratings_of_video
}
return HttpResponse(template.render(context, request))
When I try to run this I get an error 'Video' object has no attribute 'rating_set'
But when i read the django docs it tells me when you do a reverse lookup you need to use this _set.all() command. I am not sure what is missing here.
You have specified related_name in your foreign key loopkup. so rating_set should not work now.
You can lookup like
ratings_of_video = vid_rate.video.all()
A better naming convention will be to use ratings in your related_name
class Rating(models.Model):
video = models.ForeignKey('Video', related_name='ratings', null=True)
and then query like
ratings_of_video = vid_rate.ratings.all()
In Django I have the following models.
In the Supervisor model I have a many-to-many field without an explicitly defined through table. In the ForeignKey field of the Topic model I would like to refer to the automatically created intermediate model (created by the many-to-many field in the Supervisor model), but I don't know what is the name of the intermediate model (therefore I wrote '???' there, instead of the name).
Django documentation tells that "If you don’t specify an explicit through model, there is still an implicit through model class you can use to directly access the table created to hold the association."
How can I use the automatically created implicit through model class in Django in a ForeignKey field?
import re
from django.db import models
class TopicGroup(models.Model):
title = models.CharField(max_length=500, unique='True')
def __unicode__(self):
return re.sub(r'^(.{75}).*$', '\g<1>...', self.title)
class Meta:
ordering = ['title']
class Supervisor(models.Model):
name = models.CharField(max_length=100)
neptun_code = models.CharField(max_length=6)
max_student = models.IntegerField()
topicgroups = models.ManyToManyField(TopicGroup, blank=True, null=True)
def __unicode__(self):
return u'%s (%s)' % (self.name, self.neptun_code)
class Meta:
ordering = ['name']
unique_together = ('name', 'neptun_code')
class Topic(models.Model):
title = models.CharField(max_length=500, unique='True')
foreign_lang_requirements = models.CharField(max_length=500, blank=True)
note = models.CharField(max_length=500, blank=True)
supervisor_topicgroup = models.ForeignKey(???, blank=True, null=True)
def __unicode__(self):
return u'%s --- %s' % (self.supervisor_topicgroup, re.sub(r'^(.{75}).*$', '\g<1>...', self.title))
class Meta:
ordering = ['supervisor_topicgroup', 'title']
It's just called through - so in your case, Supervisor.topicgroups.through.
Although I think that if you're going to be referring to it explicitly in your Topic model, you might as well declare it directly as a model.
How can i update the existing object of intermediate model using generic view?
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Currently i'm using generic views concept to update object, but I'm facing problem hoe to update field which exist in intermediate model?
If i generate modelform for Group class, then how can i update the associated field (intermediate model field) using generic view concept?
In above i want to update invite reason field
Thanks in advance
I think there are some missing views in generic or class-based views (which I highly recommend you if your are not already using them), and other people thinks in the same way...
Take a look at django-extra-views project, it implements those missing views.