How to access model from Foreign Key, Django? - python

I have 2 models in my project. What I want to do is access CustomUser model field "user_coins". But the problem is that I need to get it with only having offer_id from the TradeOffer model. So essentially what I would like to happen is to find the TradeOffer field with offer_id and through ForeignKey get the CustomUser field user_coins that the offer_id belongs to. I can't seem to figure out how to do that.
class CustomUser(AbstractUser):
username = models.CharField(max_length=32, blank=True, null=True)
name = models.CharField(max_length=200, unique=True)
user_coins = models.FloatField(default=0.00)
class TradeOffers(models.Model):
name = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
offer_id = models.CharField(max_length=150, unique=True)
offer_state = models.IntegerField()
offer_message = models.TextField(null=True)
trade_id = models.CharField(max_length=150, unique=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)

Simple. To get the "user_coins" through "TradeOffers" objects you have to do this:
tradeoffer = TradeOffers.objects.get(offer_id = <whatever>) #Get the object.
user_coins = tradeoffer.name.user_coins #Get the user_coins field.
Or directly:
user_coins = TradeOffers.objects.get(offer_id = <whatever>).name.user_coins

Related

How to create a view for a nested serializer with foreign keys in django rest framework?

I got this code, but I can't find a way to create a view that retrieve the allergies a patient has.
class Patient(models.Model):
user = models.OneToOneField(User, related_name='patient', on_delete=models.CASCADE)
id_type = models.CharField(max_length=300)
id_number = models.CharField(max_length=300)
creation_date = models.DateField(default=datetime.date.today)
class Allergie(models.Model):
name = models.CharField(max_length=300, default="X")
class PatientAllergies(models.Model):
patient = models.ForeignKey(Patient, related_name="patient_allergies", on_delete=models.CASCADE)
allergie = models.ForeignKey(Allergie, on_delete=models.CASCADE, null=True)
professional_contract = models.ForeignKey(ProfessionalContract, null=True ,on_delete=models.CASCADE)
You can span a ManyToManyField relation over your PatientAllergies model that acts as a junction table:
class Patient(models.Model):
user = models.OneToOneField(User, related_name='patient', on_delete=models.CASCADE)
id_type = models.CharField(max_length=300)
id_number = models.CharField(max_length=300)
creation_date = models.DateField(auto_now_add=True)
allergies = models.ManyToManyField(
'Allergie',
through='PatientAllergies'
)
# …
You can then for a Patient object p with:
p.allergies.all()
An alternative is to filter the Allergie objects with:
Allergie.objects.filter(patientallergies__patient=p)
or with the ManyToManyField:
Allergie.objects.filter(patient=p)

How to write a self referencing Django Model?

I have a Django model "Inspection" which has:
InspectionID (PK)
PartID
SiteID
Date
Comment
Report
Signiture
I want to be able to have a one to many relationship between the inspection ID and date. So one ID can have inspections at many dates. How would I do this? I currently have the following:
class Inspection(models.Model):
InspectionID = models.IntegerField(primary_key=True, unique=True)
PartID = models.ForeignKey('Part', on_delete=models.CASCADE)
SiteID = models.ForeignKey('Site', on_delete=models.CASCADE)
Date = models.DateField(auto_now=False, auto_now_add=False)
Comment = models.CharField(max_length=255, blank=True)
Report = models.FileField(upload_to='docs', null=True, blank=True)
Signiture = models.CharField(max_length=255, blank=True)
I thought about using models.ForeignKey but I really don't know how to implement that properly in this situation.
I want to be able to have a one to many relationship between the inspection ID and date.
You create an extra model, like:
class InspectionDate(models.Model):
inspection = models.ForeignKey(
Inspection,
on_delete=models.CASCADE,
related_name='inspectiondates'
)
date = models.DateField()
You thus can create InspectionDates for a given Inspection.
Or if you want to add extra data, it might be better to define an InspectionGroup model:
class InspectionGroup(models.Model):
pass
class Inspection(models.Model):
id = models.AutoField(primary_key=True, unique=True, db_column='InspectionId')
inspectiongroup = models.ForeignKey(InspectionGroup, on_delete=models.CASCADE, db_column='InspectionGroupId')
part = models.ForeignKey('Part', on_delete=models.CASCADE, db_column='PartId')
site = models.ForeignKey('Site', on_delete=models.CASCADE, db_column='SiteId')
date = models.DateField(db_column='Date')
comment = models.CharField(max_length=255, blank=True, db_column='CommentId')
report = models.FileField(upload_to='docs', null=True, blank=True, db_column='ReportId')
signiture = models.CharField(max_length=255, blank=True, db_column='Signature')
Note: the name of attributes are normally written in snake_case [wiki], not in PerlCase or camelCase.
you may store 'self Foriegnkey' as
class Inspection(models.Model):
InspectionID = models.IntegerField(primary_key=True, unique=True)
PartID = models.ForeignKey('Part', on_delete=models.CASCADE)
SiteID = models.ForeignKey('Site', on_delete=models.CASCADE)
Date = models.DateField(auto_now=False, auto_now_add=False)
Comment = models.CharField(max_length=255, blank=True)
Report = models.FileField(upload_to='docs', null=True, blank=True)
Signiture = models.CharField(max_length=255, blank=True)
inspection_id = models.ForeignKey('self', null=True, blank=True)

django - Runpython function to turn charfield into foreignkey

I've been strugglin to relate a csv imported data model with a spatial data model based on a CharField.
I've created both models and now im trying to transfer the data from one field to a new one to be the ForeignKey field. I made a Runpython funtion to apply on the migration but it goives the an error:
ValueError: Cannot assign "'921-5'":
"D2015ccccccc.rol_fk" must be a "D_Base_Roles" instance.
Here are the models:
class D_Base_Roles(models.Model):
predio = models.CharField(max_length=254)
dest = models.CharField(max_length=254)
dir = models.CharField(max_length=254)
rol = models.CharField(primary_key=True, max_length=254)
vlr_tot = models.FloatField()
ub_x2 = models.FloatField()
ub_y2 = models.FloatField()
instrum = models.CharField(max_length=254)
codzona = models.CharField(max_length=254)
nomzona = models.CharField(max_length=254)
geom = models.MultiPointField(srid=32719)
def __str__(self):
return str(self.rol)
class Meta():
verbose_name_plural = "Roles"
class D2015ccccccc(models.Model):
id = models.CharField(primary_key=True, max_length=80)
nombre_archivo = models.CharField(max_length=180, blank=True, null=True)
derechos = models.CharField(max_length=120, blank=True, null=True)
dir_calle = models.CharField(max_length=120, blank=True, null=True)
dir_numero = models.CharField(max_length=120, blank=True, null=True)
fecha_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_certificado = models.CharField(max_length=50, blank=True, null=True)
numero_solicitud = models.CharField(max_length=50, blank=True, null=True)
rol_sii = models.CharField(max_length=50, blank=True, null=True)
zona_prc = models.CharField(max_length=120, blank=True, null=True)
##NEW EMPTY FOREIGNKEY FIELD
rol_fk = models.ForeignKey(D_Base_Roles, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return str(self.numero_certificado)
class Meta:
managed = True
#db_table = 'domperm2015cip'
verbose_name_plural = "2015 Certificados Informaciones Previas"
ordering = ['numero_certificado']
The Runpython function:
def pop_rol(apps, schema_editor):
roles = apps.get_model('b_dom_edificacion', 'D2015ccccccc')
for r in roles.objects.all():
rol = roles
r.rol_fk = r.rol_sii
r.save()
D_Base_Roles.rol values are all unique, and 921-5 is one of those values.
What am I missing?
You probably need to assign an object, not a string. Change the line
r.rol_fk = r.rol_sii
to
r.rol_fk = D_Base_Roles.objects.get(rol=r.rol_sii)
Maybe adjust to whatever the correct field for looking up D_Base_Roles instances is.
Note: this will make a database query for every iteration of the for-loop

DRF - filter across 2 models

I'm working with a legacy database where I have a serializer setup on Table A like so -
class TblapplicationsSerializer(serializers.ModelSerializer):
class Meta:
model = Tblapplications
fields = ('applicationid', 'applicationname', 'description', 'drtierid', 'saglink', 'supportinstructions',
'defaultincidentpriorityid', 'applicationorigintypeid', 'installationtypeid', 'comments',
'lastmodifieddate', 'lastmodifiedby', 'assetstatusid', 'recordownerid', 'adl_app')
depth = 2
I'm using a standard filter -
class TblapplicationsFilter(django_filters.FilterSet):
name = django_filters.CharFilter(name="applicationname", lookup_type="exact")
env = django_filters.CharFilter(name="adl_app__environmentid__domain")
class Meta:
model = Tblapplications
fields = ['applicationname', 'name', 'env']
Here's where it goes sideways. What I want to be able to do is filter on my URL like /api/applications/?name=xxx&env=DEV. It would then return the application and any databases that are linked with the environment of DEV. The name was understandably easy, but the only was I figured out the environment was to make the api point for applications touch the middle table that links the two but it returns multiple values because it's grabbing each time application is referenced with a separate database.
I've updated the Serializer and Filter based on comments given and the serializer, without the &env=DEV returns all the appropriate data (domain is nested in a reverse relationship). I then want my filter to filter the results based on that. Which means that it needs to somehow know to limit the results on the reverse relationship to only what's provided from the nested value.
If you see my models -
class Tblapplicationdatabaselinks(models.Model):
id = models.AutoField(db_column='ID', primary_key=True)
applicationid = models.ForeignKey('Tblapplications', db_column='applicationId', to_field='applicationid',
related_name='adl_app')
dbid = models.ForeignKey('Tbldatabases', db_column='dbId', to_field='id', related_name='adl_db')
environmentid = models.ForeignKey('Tbldomaincodes', db_column='environmentId', to_field='id',
related_name='adl_envlink')
comments = models.TextField(blank=True)
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblApplicationDatabaseLinks'
class Tblapplications(models.Model):
applicationid = models.AutoField(db_column='applicationId', primary_key=True)
applicationname = models.CharField(db_column='applicationName', max_length=255)
description = models.TextField(blank=True)
drtierid = models.ForeignKey(Tbldomaincodes, db_column='drTierID', blank=True, null=True, to_field='id',
related_name='app_drtier')
saglink = models.TextField(db_column='sagLink', blank=True)
supportinstructions = models.TextField(db_column='supportInstructions', blank=True)
defaultincidentpriorityid = models.IntegerField(db_column='defaultIncidentPriorityId', blank=True, null=True)
applicationorigintypeid = models.IntegerField(db_column='applicationOriginTypeId')
installationtypeid = models.ForeignKey(Tbldomaincodes, db_column='installationTypeId', to_field='id',
related_name='app_insttype')
comments = models.TextField(blank=True)
assetstatusid = models.ForeignKey(Tbldomaincodes, db_column='assetStatusId', to_field='id',
related_name='app_status')
recordownerid = models.ForeignKey(Tblusergroups, db_column='recordOwnerId', blank=True, null=True,
to_field='groupid', related_name='app_owner')
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblApplications'
class Tbldatabases(models.Model):
dbid = models.AutoField(db_column='dbId', primary_key=True)
dbname = models.CharField(db_column='dbName', max_length=255)
serverid = models.ForeignKey('Tblservers', db_column='serverId', to_field='serverid', related_name='db_serv')
servicename = models.CharField(db_column='serviceName', max_length=255, blank=True)
dbtypeid = models.IntegerField(db_column='dbTypeId', blank=True, null=True)
inceptiondate = models.DateTimeField(db_column='inceptionDate', blank=True, null=True)
comments = models.TextField(blank=True)
assetstatusid = models.IntegerField(db_column='assetStatusId')
recordownerid = models.IntegerField(db_column='recordOwnerId', blank=True, null=True)
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblDatabases'
class Tbldomaincodes(models.Model):
id = models.IntegerField(db_column='ID', primary_key=True)
domain = models.CharField(primary_key=True, max_length=255)
displayname = models.CharField(db_column='displayName', primary_key=True, max_length=255)
displayorder = models.IntegerField(db_column='displayOrder', blank=True, null=True)
comments = models.TextField(blank=True)
lastmodifieddate = models.DateTimeField(db_column='lastModifiedDate', blank=True, null=True)
lastmodifiedby = models.CharField(db_column='lastModifiedBy', max_length=255, blank=True)
# upsize_ts = models.TextField(blank=True) # This field type is a guess.
class Meta:
managed = False
db_table = 'tblDomainCodes'
Extend your filter set and reference the field in the other model:
class TblapplicationsFilter(django_filters.FilterSet):
name = django_filters.CharFilter(name="applicationname", lookup_type="exact")
env = django_filters.CharFilter(name="environmentid__name")
# ^^^^^^^^^^^^^^^^^^^
class Meta:
model = Tblapplications
fields = ['applicationname', 'name', 'env']
Also, you may wish to name your ForeignKey fields without the id suffix, which is the Django convention. In Django, when you access Tblapplications.environmentid, it is normally a model instance, not the actual id integer itself.

Pulling Data From Multiple Tables in Django

I'm kind of new to Django and am having some trouble pulling from existing tables. I'm trying to pull data from columns on multiple joined tables. I did find a solution, but it feels a bit like cheating and am wondering if my method below is considered proper or not.
class Sig(models.Model):
sig_id = models.IntegerField(primary_key=True)
parent = models.ForeignKey('self')
state = models.CharField(max_length=2, db_column='state')
release_id = models.SmallIntegerField(choices=releaseChoices)
name = models.CharField(max_length=255)
address = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=255, blank=True)
zip = models.CharField(max_length=10, blank=True)
phone1 = models.CharField(max_length=255, blank=True)
fax = models.CharField(max_length=255, blank=True)
email = models.EmailField(max_length=255, blank=True)
url = models.URLField(max_length=255, blank=True)
description = models.TextField(blank=True)
contactname = models.CharField(max_length=255, blank=True)
phone2 = models.CharField(max_length=255, blank=True)
ratinggroup = models.BooleanField()
state_id = models.ForeignKey(State, db_column='state_id')
usesigrating = models.BooleanField()
major = models.BooleanField()
class Meta:
db_table = u'sig'
class SigCategory(models.Model):
sig_category_id = models.IntegerField(primary_key=True)
sig = models.ForeignKey(Sig, related_name='sigcategory')
category = models.ForeignKey(Category)
class Meta:
db_table = u'sig_category'
class Category(models.Model):
category_id = models.SmallIntegerField(primary_key=True)
name = models.CharField(max_length=255)
release_id = models.SmallIntegerField()
class Meta:
db_table = u'category'
Then, this was my solution, which works, but doesn't quite feel right:
sigs = Sig.objects.only('sig_id', 'name').extra(
select = {
'category': 'category.name',
},
).filter(
sigcategory__category__category_id = categoryId,
state_id = stateId
).order_by('sigcategory__category__name', 'name')
Now since the items in filter() join the sigcategory and category models, I was able to pull category.name out by using extra(). Is this a proper way of doing this? What if I did not have the reference in filter() and the join did not take place?
SigCategory has a ForeignKey pointing at Category, so you can always get from the SigCategory to the Category simply by doing mysigcategory.category (where mysigcategory is your instance of SigCategory.
If you haven't previously accessed that relationship from that instance, doing it here will cause an extra database lookup - if you're concerned about db efficiency, look into select_related.

Categories