Django Queryset foreign keys - python

I am trying to get a queryset but it is not displaying anything. Basically, I want to get the Asset objects that are assigned via foreign key to an employee, which is a foreign key of the signed in user.
views.py
def get_queryset(self):
assetlist = Asset.objects.filter(organisation__employee__user=self.request.user)
print(assetlist)
return assetlist
models.py
class Employee(models.Model):
name = models.CharField("Employee Name", max_length=50, blank=False)
email = models.CharField("Employee Email", max_length=50, blank=True)
user = models.ForeignKey(User)
clientID = models.ForeignKey(Organisation)
def save(self):
self.name = self.user.get_full_name()
self.email = self.user.email
super(Employee, self).save()
def __str__(self):
return self.name
class Asset(models.Model):
name = models.CharField("Asset Name", max_length=30, primary_key=True)
organisation = models.ForeignKey(Organisation)
def __str__(self):
return self.name
class Organisation(models.Model):
name = models.CharField("Organisation Name", max_length=50, blank=False)
location = models.TextField("Organisation Address", max_length=200, blank=True)
tel = models.CharField("Telephone Number", max_length=20)
def __str__(self):
return self.name

There is no employee field inside organisation. It's an reversed relation, there are many employees attached so you can't query it like that.
But there is something called related_name in django foreign keys, with use of that, your query should look like that:
assetlist = Asset.objects.filter(organisation__employee_set__user=self.request.user)
or if you specify your own related_name into employee -> organisation relation:
clientID = models.ForeignKey(Organisation, related_name="employees")
it will look like this:
assetlist = Asset.objects.filter(organisation__employees__user=self.request.user)

The answer was to approach from another model, as seen below:
assetlist = Sensor.objects.filter(asset__organisation__employee__user=self.request.user)

You have written wrong code. You want an Asset object by using:
assetlist = Asset.objects.filter(organisation__employee__user=self.request.user)
But you clearly can see in your models.py that there is no relationship between Organisation and Employee, then how can you get a result using organisation__employee...?
You should first create a ForeignKey field to relate with Employee model then your code will work fine.

Related

populating foreign key in django

I'm creating a page that lets only admin add some assets. Each asset has a type. I have used a dropdown to select the asset_type. The selected value of asset_type gets passed into views.py but I can't get it written into the newly created asset object.
Here is my models.py
class assetType(models.Model):
title = models.CharField(max_length=150)
#property
def get_type(self):
return asset.objects.filter(asset_type=self.id)
def __str__(self):
return f"{self.title}"
class Meta:
verbose_name_plural = 'Asset Types'
class asset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, null=False)
asset_type = models.ForeignKey('assetType', on_delete=models.CASCADE, null=True)
asset_name = models.CharField(max_length=30, null=True) #unique=True
location = models.CharField(max_length=30, null=True)
brand = models.CharField(max_length=30, null=True)
purchase_year = models.PositiveIntegerField(blank=True, null=True)
isActive = models.BooleanField(default=True, null=True)
currentOwner = models.ForeignKey(User, default='', null=True, on_delete=models.CASCADE)
Here is createAssetView from views.py
#user_passes_test(lambda u: u.is_superuser)
def createAssetView(request):
assetTypeList = assetType.objects.all() # use assetType.title
assettype = request.POST.get('asset-type')
assetname = request.POST.get('asset-name')
locationn = request.POST.get('location')
brandd = request.POST.get('brand')
purchaseyear = request.POST.get('purchase-year')
isActivve = request.POST.get('is-active','') == 'on'
cuser=request.user
context={
"cuser":request.user,
"asset_type_list":assetTypeList,
"asset_type":assettype,
"asset_name":assetname,
"location":locationn,
"brand":brandd,
"purchase_year":purchaseyear,
"isActive":isActivve,
'iterator':range(2014,2050)
}
if request.method == 'POST':
new_asset = asset()
new_asset.asset_type_title=request.POST.get('asset-type')
new_asset.asset_name=assetname
new_asset.location=locationn
new_asset.brand=brandd
new_asset.purchase_year=purchaseyear
new_asset.isActive=True if isActivve else False
new_asset.currentOwner=cuser
print(assettype) # PRINT assettype
new_asset.save()
return redirect('createAssets')
return render(request, 'assets/createAsset.html', context)
The PRINT assettype statement prints selected asset type from the form, so the value is getting passed to the view, how should I populate the table with it?
Any suggestions or help will be highly appreciated. Thanks!
new_asset.asset_type_title=request.POST.get('asset-type')
This is the line where your problem is. You can't assign a foreign object like that, it does not automatically search for a match in another model.
You need to either provide the object to be used as a foreign key, or the object's primary key.
So we find our database entry for the selected type:
target_type = assetType.objects.get(title=assettype)
# this assumes you use unique titles for each assetType, see below
and then provide the new asset either with the object itself:
new_asset.asset_type = target_type
or its primary key:
new_asset.asset_type_id = target_type.pk
I strongly reccomend spending more time with django's documentation to strengthen your understanding of how foreign object relation is implemented in django. At least review the tutorials that focus on that.
Also consider the following:
The title field of the assetType model is not limited to be unique. What happens if two assetTypes with the same title are created?
Repetition of request.POST.get('asset-type')

Django - Get name of model object by iterating through class

I'm new to Python (and pretty inexperienced at programming in general), but I have an issue I can't for the life of me figure out.
I'm trying to pre-populate a field in my database with the name of an instance from another model/class in my database. The model with the field I want to pre-populate is an "instance" of the model instance from which I'm trying to grab the name, and has a foreign key to that instance.
Goal: 1) User selects the parent of the object by assigning the foreign key to the parent 2) A function grabs the name of the parent instance matching the foreign key the user selected. 3) the result from that function is used as the default value for the field.
Here's the code:
class Injury(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular injury')
name = models.CharField(max_length=200, help_text='Enter an injury or complication (e.g. respiratory failure)')
description = models.TextField(max_length=1000, blank=True, help_text='Describe the injury')
time_to_onset = models.PositiveIntegerField(blank=True, validators=[MaxValueValidator(10000)], help_text='Enter expected time from trigger until injury/complication onset')
findings = models.TextField(max_length=1000, blank=True, help_text='Enter the signs and symptoms of the injury or complication')
vitals_trends = models.TextField(max_length=1000, blank=True, help_text='Enter the vitals changes due to the injury')
class Meta:
ordering = ['name']
def __str__ (self):
return self.name
def get_absolute_url(self):
return reverse('Injury-detail', args=[str(self.id)])
class Injury_Instance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular injury')
parent_case = models.ForeignKey(PFC_Case, on_delete=models.SET_NULL,null=True)
injury_model = models.ForeignKey(Injury, on_delete=models.SET_NULL, null=True)
def set_injury_name(self):
for injuries in Injury.all()
if injury_model == injuries
break
return Injury.name
name = dislay_models.CharField(default=set_injury_name(self,Injury,injury_model), max_length=100)
triggered_by = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True)
def __str__ (self):
return self.name
def get_absolute_url(self):
return f'{self.id} ({self.Injury.name})'
The problem area is def set_injury_name and Injury_Instance.name
Thanks!!!
Edit:
I tried the following code, but I'm getting the error 'NameError: name 'self' is not defined'
class Injury_Instance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular injury')
parent_case = models.ForeignKey(PFC_Case, on_delete=models.SET_NULL,null=True)
injury_model = models.ForeignKey(Injury, on_delete=models.SET_NULL, null=True)
def get_injury_name(self):
return self.name
injury_name=get_injury_name(self)
name = models.CharField(default=injury_name, max_length=100)
triggered_by = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True)
def __str__ (self):
return self.name
def get_absolute_url(self):
return f'{self.id} ({self.Injury.name})'
You don't need to store the name of your foreign key field as you always can access it with:
self.injury_model.name
If you need to get access it just by name you can write a property in Injury_Instance model.
#property
def name(self):
return self.injury_model.name

Models in Python Django not working for Many to Many relationships

I am trying to create the proper Django model that could fit the following reqs:
Person Class has 1 to many relations with the Address Class
Person Class has many to many relations with the Group Class
Book Class contains the collections of the Persons and the Groups
This is my code:
class Person(models.Model):
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=20)
def __str__(self):
return self.first_name+ ' - ' + self.last_name
class Address(models.Model):
person = models.ForeignKey(Person)
address_line = models.CharField(max_length=200)
def __str__(self):
return self.address_line
class Group(models.Model):
group_name = models.CharField(max_length=12)
persons = models.ManyToManyField(Person)
def __str__(self):
return self.group_name
class Book(models.Model):
record_name = models.CharField(max_length=12)
person = models.ForeignKey(Person )
group = models.ForeignKey(Group )
def __str__(self):
return self.record_name
However it's not correct:
1) A Group can now contain multiple Persons but the Persons do not contain any Group.
I am not sure if I should add to the Person class the following code:
groups = models.ManyToManyField(Group)
2) The Book class now contains only 1 record of Person & Group per Book record.
3) When I added the Foreign Keys to the models, I removed
on_delete tag:
person = models.ForeignKey(Person, on_delete=models.CASCADE())
because it does not compile it, asking for some params.
I know how to make all this for C#, but I am a kinda stucked with this simple task in Python/Django.
1) The ManyToMany field should appear only in one of the models, and by looks of things you probably want it in the Person model.
Its important to understand that the data about the ManyToMany field is saved in a differant table. Django only allows this field to be visable through buth models (so basiclly, choose where it is move convinient).
2)By the look of your structure I will suggest you use a ManyToMany field through a different table. here is an example:
class Activity(models.Model):
name = models.CharField(max_length=140)
description = models.TextField(blank=True, null=True)
class Route(models.Model):
title = models.CharField(max_length=140)
description = models.TextField()
activities_meta = models.ManyToManyField(Activity, through = 'RouteOrdering')
class RouteOrdering(models.Model):
route = models.ForeignKey(Route, on_delete=models.CASCADE)
activity = models.ForeignKey(Activity, on_delete=models.CASCADE, related_name='activita')
day = models.IntegerField()
order = models.IntegerField(default=0)
that way the data is binded to the ManyToMany field

Django multiple Foreign Key - Display related field in details admin page for add/edit

I have a polling app with one of the models "Choice" consisting of 2 Foreign key fields linked to the "Person" model.
I wanted to automatically populate related "photo_other" field (with the image link) once I have selected the "name" of the person. "name" is also a Foreign Key Field linked with Choice model.
models.py
class Choice(models.Model):
name = models.ForeignKey(Person)
photo_other = models.ForeignKey(Person)
rating = models.DateTimeField(blank=True, null=True)
def __unicode__(self):
return smart_unicode(self.name)
class Person(models.Model):
name = models.CharField(max_length=250)
photo = models.ImageField(upload_to="photos")
pub_date = models.DateTimeField()
def __unicode__(self):
return smart_unicode(self.name)
Why do you want to store the same value in two different tables when they are connected through a foreign key? It just doesn't make sense.
class Choice(models.Model):
name = models.ForeignKey(Person)
rating = models.DateTimeField(blank=True, null=True)
#property
def photo_other(self):
return self.name.photo
class Person(models.Model):
name = models.CharField(max_length=250)
photo = models.ImageField(upload_to="photos")
pub_date = models.DateTimeField()
In order to make photo_other visible under the admin page of Choice model, you can do the following;
class ChoiceAdmin(admin.ModelAdmin):
list_display = ['name', 'rating', 'get_photo']
def get_photo(self, obj):
return obj.photo_other
get_photo.short_description = 'Photo'

NameError: name 'ManyToManyField' is not defined

I'm trying to use a ManyToMany relationship and it is giving me the following error:
NameError: name 'ManyToManyField' is not defined
Background: Building a to do app where users have (many) projects, projects have (many) lists of tasks and projects have (many) tags that characterise them.
Here is my models.py, any help catching the error would be greatly appreciated.
from django.db import models
from django.contrib.auth.models import User
#Not sure if I need the ID's. They may be superfluous. Ask in the lab today.
#Used to list collaborators on projects and track friends lists
#Borrowed from http://stackoverflow.com/a/1113039/1254402
class SeparatedValuesField(models.TextField):
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
self.token = kwargs.pop('token', ',')
super(SeparatedValuesField, self).__init__(*args, **kwargs)
def to_python(self, value):
if not value: return
if isinstance(value, list):
return value
return value.split(self.token)
def get_db_prep_value(self, value):
if not value: return
assert (isinstance(value, list) or isinstance(value, tuple))
return self.token.join([unicode(s) for s in value])
def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
class UserProfile(models.Model):
user_id = models.CharField(max_length=100, null=True, blank=True, unique=True)
user = models.OneToOneField(User)
# The additional attributes we wish to include.
first_name = models.CharField(max_length=64)
surname = models.CharField(max_length=64)
friends = SeparatedValuesField()
picture = models.ImageField(upload_to='profile_images', blank=True)
projects = models.ManyToManyField('Project')
# This line is required. Links UserProfile to a User model instance.
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
#Project model.
#Attributes = name, website, team members
#Many users can have many projects
class Project(models.Model):
project_id = models.CharField(max_length=100, null=True, blank=True, unique=True)
name = models.CharField(max_length=128)
description = models.CharField(max_length=300)
website = models.URLField(blank=True)
team_members = SeparatedValuesField()
class List(models.Model):
#Many lists belong to one project
project = models.ForeignKey(Project)
tasks = ManyToManyField('Task')
name = models.CharField(max_length=128)
colour = models.CharField(max_length=10)
#NOTE! - Abstracting the tags (category, progress and priority) to project level.
class Task(models.Model):
#Many tasks belong to one list
belong_to_list = models.ForeignKey(List)
#Unique id for task
task_id = models.CharField(max_length=100, null=True, blank=True, unique=True)
#Standard title & description
title = models.CharField(max_length=100)
description = models.CharField(max_length=300)
#NOTE! - Abstracting the tags (category, progress and priority) to project level.
class Tag(models.Model):
project = models.ForeignKey(Project)
#UUID
task_id = models.CharField(max_length=100, null=True, blank=True, unique=True)
#User assigns each tag a colour. hex code.
colour = models.CharField(max_length=10)
In List, you are referring to ManyToManyField without referencing it via models as you do with all the other fields.
Note that the error message would have told you exactly where the problem was, so that you wouldn't have needed to post all the other irrelevant code.

Categories