I have an API which I pass some sample data. I am overwriting the post method by copying the Queryset so I can manipulate the output data. I would like to access the value of a foreign key relationship but I can only access the foreign key itself.
Like so:
def post(self, request, *args, **kwargs):
data_request = request.data
data_request = data_request.copy()
machine_na = data_request.__getitem__('project')
##this gives me the id of the foreign key
data_request.__setitem__('project', str('my value'))
return Response(data_request, *args, **kwargs)
Now that works. But I can't access the name of the foreign key.
My models as Foreign Keys:
class Machine(models.Model):
machine_name = models.CharField(max_length=120, primary_key=True)
def __str__(self):
return self.machine_name
class Project(models.Model):
project_name = models.CharField(max_length=120, primary_key=True)
def __str__(self):
return self.project_name
My model that refers to the others:
class Simulation(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
machine = models.ForeignKey(Machine, on_delete=models.CASCADE, default=1)
project
I hope I am clear enough. I would like to access the specific name of, for example, foreign key 2.
calling 'project.project_name' doesn't work and everything else I tried also not.
Any help is highly appreciated. Thanks in advance
Get the project object using the key and then get the name from the object.
project=Project.objects.get(id=int(self.request.POST['project']))
machine_na = project.project_name
Related
I have a Django model which has relationship with user model. Where user are assigned to groups. especially "Admin", "Teacher","Student". So I want to make a foreign key relationship in such a way that it will show only The users that have been assigned to Teacher groups for Teacher_details model, And Similar for Student_Details Model. I have made the models Teacher_Details , Student_Details and established foreign key relation with User model. But the problem is that its showing all the user when I am filling Student_Details or Teacher_Details. Hope you got my problem.
I am hoping positive response.
The code looks like this:
class Student_Details(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
image = models.ImageField(default='none', upload_to='img/')
details_updated = models.DateTimeField(auto_now_add=True)
address = models.CharField(max_length=150)
admission_date = models.DateField()
previous_college = models.CharField(max_length=150)
course_enrolled = models.ForeignKey(ModelUniversity,on_delete=models.CASCADE)
semester = models.CharField(max_length=20,choices=semester,default=None)
def __str__(self):
return self.user.first_name
class Teacher_Details(models.Model):
address = models.CharField(max_length=150)
image = models.ImageField(default='none', upload_to='img/')
details_updated = models.DateTimeField(auto_now_add=True)
subject_taught = models.ManyToManyField(to='Student.stu_subject')
user = models.OneToOneField(User,on_delete=models.CASCADE)
def __str__(self):
return self.user.first_name
def subject_teacher_teaches(self):
return [str(s) for s in self.subject_taught.all()]
Since both models have a user_id reference, you could use that info to search both models based on the request and fetch the necessary instance. Make a view which checks the user_id in the request, search both models and return the results (I assume a user cannot belong to both groups...)
I want to keep the latest record of a user:
class Record(models.Model):
name = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='site_pics')
date = models.DateTimeField(null=True, blank=True, auto_now_add=True)
def save(self, *args, **kwargs):
super(Record, self).save(*args, **kwargs)
numdata = Record.objects.select_related('name').count()
print(numdata)
#if numdata > 1:
# Record.objects.select_related('name').first().delete()
As per this post Filter latest record in Django, I tried:
.distinct()
.select_related()
.prefetch_related()
None of them return the correct number of records or don't work at all because I'm using SQLite.
Thank you for any suggestions
In that case it might be better to change the modeling to a OneToOneField, such that the database will reject a second Record for the same user. You might also want to change the name of the relation to user, since you are referring to a user object, not its name.
In the save(…) method, you can look if the primary key is not yet filled in, if that is the case, you can delete the original record of the user. Regardless whether that exists or not. If this records does not exist, then it will act as no-op, where nothing changes in the database:
class Record(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='site_pics')
date = models.DateTimeField(null=True, blank=True, auto_now_add=True)
def save(self, *args, force_insert=False, **kwargs):
if self.pk is None or force_insert:
Record.objects.filter(user_id=self.user_id).delete()
return super().save(*args, force_insert=force_insert, **kwargs)
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I have the following models:
class STUser(AbstractBaseUser):
email = models.EmailField(unique=True)
name = models.CharField(max_length=255)
...
class VenuePermissions(models.Model):
user = models.ForeignKey(STUser, on_delete=models.CASCADE)
venue = models.ForeignKey(Venue, on_delete=models.CASCADE, blank=True, null=True)
...
class Venue(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=1500, null=True, blank=True)
...
I am then prefetching the related venuepermission objects to a STUser object in a view
class VenueUserList(APIView):
def get(self, request, *args, **kwargs):
objects = STUser.objects.prefetch_related('venuepermissions_set').all()
...
Then I want to take the returned query set and replace the venue FKs with their objects.
for item in objects:
for permission in item_venuepermissions_set:
permission_venue = Venue.objects.get(pk=permission_venue)
print(repr(objects))
...
return Response({})
but my approach is clearly wrong. how do I properly access a field of a queryset and change its value?
As you can see I need to do it twice. Once to access the current objects permission_set and again to access that permission_set venue field and override it.
I do not want any of this changing the database. This is just to return the values.
update:
I made the following changes to get access to the individual fields:
for item in objects:
for permission in item.venuepermissions_set:
permission.venue = Venue.objects.get(pk=permission.venue)
print(repr(objects))
return Response({})
the new error I have is:
TypeError: 'RelatedManager' object is not iterable
trying to resolve
Answering all my questions today:
class VenueUserList(APIView):
def get(self, request, *args, **kwargs):
objects = STUser.objects.prefetch_related('venuepermissions_set').all()
for item in objects:
for permission in item.venuepermissions_set.all():
permission.venue = Venue.objects.get(pk=permission.venue_id)
return Response({})
is the way to do it
I have two models like
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
Now for an object of Article lets say
a=Article.objects.filter(id=1)
a=a[0]
I try to change the headline and the email of the author who has written this article so I do
a.heagline = "Saving foreign key does not work"
a.reporter.email = "changed#email.com"
a.save()
This saves the Article object but does not modify the Reporter.
I explicitly have to do
a.reporter.save()
to see the changes to the reporter object. As this is a Many to One relation it should also modify the Foreign key on saving
How can I save the parent Model too by just calling the childs save method
You could override the save method or just create a custom method.
class Article(models.Model):
...
# Overriding save
def save(self, *args, **kwargs):
self.reporter.save()
super(Article, self).save(*args, **kwargs)
# Creating a custom method
def save_related(self):
self.reporter.save()
self.save()
I suggest you create a custom method because it doesn't introduce unexpected behavior in save()
What is the correct way of getting the 'contact' count from within my 'Group'?
I was thinking of just creating a new method within 'group' and filter(), but this means hitting the db again which seems bad, right?
class GroupManager(models.Manager):
def for_user(self, user):
return self.get_query_set().filter(user=user,)
class Group(models.Model):
name = models.CharField(max_length=60)
modified = models.DateTimeField(null=True, auto_now=True,)
#FK
user = models.ForeignKey(User, related_name="user")
objects = GroupManager()
def get_absolute_url(self):
return reverse('contacts.views.group', args=[str(self.id)])
class Contact(models.Model):
first_name = models.CharField(max_length=60)
last_name = models.CharField(max_length=60)
#FK
group = models.ForeignKey(Group)
group_object.contact_set.count() should do it. Django creates the relation by adding _set to the end of the foreign key's model name.
Have a look at the docs on related objects for more info.