Using getattrs() to access Foregin Key values - python

I am using a basic form in Django to collect a users choices which will be used to create a filter of objects and then output to csv. I would like to use the values from the form to access data in the different models.
My form looks like this..
class CustomReportForm(forms.Form):
CHOICES=[('Asset Labels','Asset Labels'),
('Asset List','Asset List')]
REPORT_FIELDS = [('id','ID'),
('name','Name'),
('location','Location'),
('status','Status'),
]
type = forms.ChoiceField(choices=CHOICES)
col_choices = forms.MultipleChoiceField(choices=REPORT_FIELDS, widget=forms.CheckboxSelectMultiple)
location = forms.ModelChoiceField(AssetLocation.objects.all(), required=False)
status = forms.ModelChoiceField(AssetStatus.objects.all(), required=False)
I have 2 models included in the form 'AssetLocation' and 'AssetStatus'.
class AssetLocation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
location = models.CharField(max_length=20)
location_code = models.CharField(max_length=10, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.company) + " - " + self.location
class AssetStatus(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
status = models.CharField(max_length=20)
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.company) + " - " + self.status
I also have an Asset model
class Asset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
location = models.ForeignKey(AssetLocation, on_delete=models.CASCADE)
status = models.ForeignKey(AssetStatus, on_delete=models.CASCADE)
name = models.CharField(max_length=40)
def __str__(self):
return str(self.company) + " - " + self.name
And I have a view which accesses the POST data and tries to use that to get data.
def AssetList(request):
assets = Asset.objects.all()
cols = request.POST.getlist('col_choices')
for a in assets:
data = []
for i in cols:
data.append(getattr(a,i))
print(data)
This works as expected. I am getting the location and status of each asset but its returning the def str of AssetLocation and AssetStatus.
I would like to access AssetLocation.location and AssetStatus.status.
I have tried to modify the form choices to this but it generates a 'Asset' object has no attribute 'location.location' error
REPORT_FIELDS = [('id','ID'),
('name','Name'),
('location.location','Location'),
('status.status','Status'),
]
How can I access foreign key values with the getattr() function?
thanks
James

You'll have to be cleverer in your view code. You could try splitting on '.':
for a in assets:
data = []
for i in cols:
if '.' in col:
fk, field = col.split('.')
val = getattr(getattr(a, fk), field)
else:
val = getattr(a,i)
data.append(val)
Of course, this will break if you have more than one level of relationship.

Related

django get to every user if its latest record match given value in table

I want to filter students if his last record transaction_type match with given value.
For example Student Ali has 3 record in transaction table. And if the latest records transaction_type == 'busy' I want to get this transaction otherwise I want to pass this transaction
My Models like that
class Type(models.Model):
type = models.CharField(max_length=50)
def __str__(self):
return self.durum
class Student(models.Model):
ogr_no = models.CharField(max_length=10, primary_key=True)
ad = models.CharField(max_length=50)
soyad = models.CharField(max_length=50)
bolum = models.CharField(max_length=100,blank=True)
dogum_yeri = models.CharField(max_length=30)
sehir = models.CharField(max_length=30)
ilce = models.CharField(max_length=30)
telefon = models.CharField(max_length=20,blank=True, null=True)
nufus_sehir = models.CharField(max_length=30,blank=True, null=True)
nufus_ilce = models.CharField(max_length=30,blank=True, null=True)
def __str__(self):
return self.ogr_no + " " + self.ad + " " + self.soyad
class Transaction(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='islemogrenci')
transaction_type = models.ForeignKey(Type, on_delete=models.CASCADE)
yardim = models.ForeignKey(Yardim, on_delete=models.CASCADE, blank=True, null=True)
aciklama = models.CharField(max_length=300,blank=True, null=True)
transaction_date = models.DateTimeField(blank=True,null=True)
transaction_user = models.ForeignKey(User, on_delete=models.CASCADE,null=True,blank=True)
def __str__(self):
return self.student.ad + " " + self.transaction_type.durum
Note: I use Postgres as Database Engine
One solution could be to get the latest records of all students and then check the transaction_type.
latest_records = Transaction.objects.values('student').annotate(
latest_record=Max('id')
)
transactions = Transaction.objects.filter(
id__in=latest_records.values('latest_record'),
transaction_type='busy'
)

how can i select correctly many to many field django

I need to select 'changes' which related to sku id
I need help with views.py
models.py
Change
class Change (models.Model):
raw_current = models.ForeignKey(Raw, blank=True, null=True, on_delete=models.CASCADE, related_name='raw_current')
raw_new = models.ForeignKey(Raw, blank=True, null=True, on_delete=models.CASCADE, related_name='raw_new')
created_date = models.DateTimeField(default=timezone.now) # когда была создана заявка
def __str__(self):
return self.raw_current.num
def publish(self):
self.created_date = timezone.now()
self.save()
Raw
class Raw (models.Model):
num = models.CharField(max_length=200) # артикул сырья
name = models.CharField(max_length=200) # наименование
layer = models.CharField(max_length=200) # название слоя на русском
def __str__(self):
return self.num +' ' + self.name
Sku
class Sku (models.Model):
num = models.CharField(max_length=200) # артикул готоваой продукции (ГП)
name = models.CharField(max_length=200) # наименование ГП
raw = models.ManyToManyField(Raw, blank=True, null=True) # сырье
weight = models.IntegerField(blank=True, null=True) # вес
photo = models.ImageField(blank=True, null=True,
upload_to="images/") # фото
type = models.ForeignKey(ProductsTypes, blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.num + ' ' + self.name
views.py
def change(request,sku_id):
sku = Sku.objects.get(id=sku_id)
list_change = Change.objects.filter(raw_current = sku.raw)
return render(request, 'main/change.html', {'sku':sku,'list_change':list_change,'change':change,})
urls.py
path('change/<sku_id>', views.change, name='change'),
TypeError at /change/1
Field 'id' expected a number but got <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x10920d9f0>.
if in
views.py
def change(request,sku_id):
sku = Sku.objects.get(id=sku_id)
list_change = Change.objects.all()
return render(request, 'main/change.html',{'sku':sku,'list_change':list_change,'change':change,})
then i have the whole list but i need only changes belongs to selected sku
thanks for help
Because your raw field in Sku model is a ManyToManyField, you CANNOT do things like this:
list_change = Change.objects.filter(raw_current = sku.raw)
A ManyToManyField means that you can store not only one Raw in the Sku.raw field, and you can use sku.raw.all() to see all the Raws related to a specific sku object.
You can see the official document here.
Thus, if you want to filter all the Changes whose raw_current are equal to a bunch of Raws belongs to a sku, you can try something like this:
list_change = Change.objects.filter(raw_current__in=sku.raw.all())

model.objects.all() doesn't find anything when foreign key in model

when I load the website i get this error
my models.py file looks like:
# Create your models here.
class Information(models.Model):
id = models.CharField(max_length=200, primary_key=True)
title = models.CharField(max_length=500)
link = models.CharField(max_length=100)
summary = models.CharField(max_length=1000)
published = models.CharField(max_length = 100)
def __str__(self):
return self.title
class Search(models.Model):
id = models.CharField(max_length=100, primary_key=True)
searched_titles = models.CharField(max_length=100)
searched_topics = models.CharField(max_length=100)
number_found_articles = models.IntegerField()
def __str__(self):
return self.id
class Article_search(models.Model):
id = models.AutoField(primary_key=True)
found_articles = models.ForeignKey(
Information, on_delete=models.CASCADE)
search_details = models.ForeignKey(
Search, on_delete=models.CASCADE)
def __str__(self):
return self.id
in my view.py file:
def show_articles_with_this_filter_id(request):
all = Article_search.objects.all()
print(all)
return render(request, 'show_article.html')
when I get to the print statement I get the error shown in the picture:
Unknown column 'database_article_search.found_articles_id' in 'field list'
why is the part _id pasted behind found_articles?
this is the error i get when i remove the id from article_search
id error when printing Article_search.objects.all()
# Create your models here.
class Information(models.Model):
title = models.CharField(max_length=500)
link = models.CharField(max_length=100)
summary = models.CharField(max_length=1000)
published = models.CharField(max_length = 100)
def __str__(self):
return self.title
class Search(models.Model):
searched_titles = models.CharField(max_length=100)
searched_topics = models.CharField(max_length=100)
number_found_articles = models.IntegerField()
def __str__(self):
return self.searched_titles
class Article_search(models.Model):
found_articles = models.ForeignKey(
Information, on_delete=models.CASCADE)
search_details = models.ForeignKey(
Search, on_delete=models.CASCADE)
Make model like this and then run two commands
1.python manage.py makemigrations and then 2.python manage.py migrate
"In your views.py file"
def show_articles_with_this_filter_id(request,id):
all = Article_search.objects.filter(id=id)
print(all)
return render(request, 'show_article.html')

How to do auto assign in django

I am working on a django project. where there's two table one is developer table and another one is Jira table. developer table and jira table are connected with m2m relation.
here's my model.py
class developer(models.Model):
Developer_Name = models.CharField(max_length=100, unique=True)
Role = models.CharField(max_length=500)
Level = models.CharField(max_length=30)
Expertise = models.CharField(max_length=200)
Availability_Hours = models.CharField(max_length=500)
def __str__(self):
return self.Developer_Name
class jira(models.Model):
Jira_ID = models.CharField(max_length=100, blank=True)
Jira_Story = models.CharField(max_length=500)
Short_Description = models.CharField(max_length=500)
Story_Points = models.CharField(max_length=30)
Sprint = models.CharField(max_length=200)
DX4C_Object = models.CharField(max_length=500)
Developer = models.ManyToManyField(developer)
Sandbox = models.ForeignKey(environments, on_delete=models.CASCADE, limit_choices_to={'Mainline': None},blank=True, null=True)
def developer_assigned(self):
return ",".join([str(p) for p in self.Developer.all()])
Now my query is how to set a rule where if Dx4c object is changing then automatically one developer will assign based on the rule?
here's my view.py
def dependency_management(request):
jira_story = jira.objects.all()
return render(request, 'hello/Dependency_Management.html', {'JIRA': jira_story})
I want to make that dynamic. I mean if everytime I add any new DX4C object then without the code change that particular developer will assign based on the rule
Something like this:
class Developer(models.Model):
name = models.CharField(max_length=100, unique=True)
role = models.CharField(max_length=500)
level = models.CharField(max_length=30)
expertise = models.CharField(max_length=200)
availability_hours = models.CharField(max_length=500)
def __str__(self):
return self.name
class Jira(models.Model):
Jira_ID = models.CharField(max_length=100, blank=True)
story = models.CharField(max_length=500)
story_points = models.CharField(max_length=30)
sprint = models.CharField(max_length=200)
DX4C_Object = models.CharField(max_length=500)
developers = models.ManyToManyField(developer)
sandbox = models.ForeignKey(
environments,
on_delete=models.CASCADE,
limit_choices_to={'Mainline': None},
blank=True, null=True,
)
def developer_assigned(self):
return ",".join(self.developers.values_list('name', flat=True))
def save(self, *args, **kwargs):
if pk := getattr(self, 'id', 0):
old_value = self.__class__.objects.get(id=pk).DX4C_Object
super().save(*args, **kwargs)
if pk and self.DX4C_Object != old_value:
# do sth

Trying to insert a new column with a list of foreign field in django_tables2

I'm using the django_tables2 to show a list of "repair details". So far so good. However I want to add a new field (it's not in the model): a list of service reports. The relation is 1 to many. and show the serial number which is in another model. It's quite difficult since I add the field but the render_NEW_FIELD doesn't work and i couldn't reach the list of service reports since in the table model I have just access to the record and not to the repair_detail model. I'm using django_tables 0.15
repair/models.py
class RepairDetail(models.Model):
repair = models.ForeignKey('Repair')
repair_detail_number = models.IntegerField()
article_code = models.CharField(max_length=30)
registered_date = models.DateField(null=True)
registered_uid = models.IntegerField(null=True)
registered_initials = models.CharField(max_length=2, null=True)
customer_reference = models.CharField(max_length=20, null=True)
db2_recnum = models.IntegerField()
def __unicode__(self):
return str(self.repair_detail_number)
class ServiceReport(models.Model):
repair_detail = models.ForeignKey('RepairDetail')
status = models.ForeignKey('ServiceReportStatus', on_delete=models.PROTECT)
serial_number = models.ForeignKey('core.SerialNumber')
customer = models.ForeignKey('core.Company')
contact = models.ForeignKey('core.Contact', null=True, on_delete=models.SET_NULL)
project = models.ForeignKey('core.Project')
project_code = models.CharField(max_length=4)
identifier = models.CharField(max_length=1)
repair_date = models.DateField(null=True)
repair_uid = models.IntegerField(null=True)
repair_initials = models.CharField(max_length=2, null=True)
booking_date = models.DateField(null=True)
core/models.py
class SerialNumber(models.Model):
product = models.ForeignKey("Product")
panel = models.ForeignKey("Panel", null=True, blank=True, default = None)
serial_number = models.CharField(max_length=30, default='')
manifest = models.TextField(null=True)
def __unicode__(self):
return self.serial_number
repair/tables.py
class RepairDetailTable(tables.Table):
#serials = tables.Column(accessor='servicereport.serialnumber.serialnumber')
serial = tables.Column()
def __init__(self, *args, **kwargs):
super(RepairDetailTable, self).__init__(*args, **kwargs)
class Meta(object):
model = RepairDetail
fields = ('id', 'repair_detail_number', 'article_code', 'registered_date', 'registered_initials', 'customer_reference', 'serials')
attrs = {'class': 'table table-striped table-bordered protonic'}
empty_text = "No records found."
If you want (1:N instead of N:1) to concatenate all related models in the table cell try to do this in your model layer by setting property, something like this:
class RepairDetail(models.Model):
# ...
#property
def service_reports_list(self):
return self.servicereport_set.all()
Define your own column (inherit tables.Column) and override render method
Add it to your table class:
class RepairDetailTable(tables.Table):
# ...
service_reports_list = YourOwnColumn(some_kwargs)
# ...

Categories

Resources