How to print foreignkey Model relation? - django

If in My model, Moneybook have a many moneylogs.
so, I design a model
Moneybook/models.py
name = models.CharField(max_length=30, default="행복한 여행!")
owner = models.ForeignKey(
user_models.User, on_delete=models.CASCADE, related_name="owner")
companion = models.ManyToManyField(
user_models.User, related_name="companion", blank=True)
country = CountryField()
location = models.CharField(max_length=50, blank=True)
start_date = models.DateTimeField(default=NOW)
end_date = models.DateTimeField(default=NOW)
Moneylog/models.py
moneybook = models.ForeignKey(
moneybook_models.Moneybook, on_delete=models.CASCADE, related_name="moneybooks")
payer = models.ForeignKey(
user_models.User, on_delete=models.CASCADE, related_name="payer")
dutch_payer = models.ManyToManyField(
user_models.User, related_name="dutch_payer")
price = models.IntegerField()
category = models.CharField(max_length=10)
memo = models.TextField()
If i want to load all the moneylogs in the each belonging moneybook. how can i load it?
I guess...
def moneybook_detail(request, pk):
moneylogs=moneylog.filter(moneylog.moneybook.id=request.moneybook.id)
return render(request, "moneybooks/detail.html")
but error occured.
moneylogs = moneylog.filter(request.moneybook.id=request.moneybook.id)
SyntaxError: keyword can't be an expression

You can either query the Moneylog table with the following query by using the double underscore __ to filter based on referenced object fields.
moneylogs = MoneyLog.filter(moneybook__id=<<<MoneyBookID_GOES_HERE>>>)
Or by using the internal ReverseManyToOneManager in Django
just by using
moneybook = MoneyBook.objects.get(pk=<<<<MoneyBookID_GOES_HERE>>>>)
moneylogs = moneybook.moneylog_set.all() # all() to get all money logs
# You can do filter(...) on it too to filter the moneylogs too.
this will return all money logs related to the money book.

In general, you have to use double underscore __ to reference foreign key columns in filters:
def moneybook_detail(request, pk):
moneylogs=moneylog.filter(moneybook__id=request.moneybook.id)
return render(request, "moneybooks/detail.html")

Related

When "select_related" is needed?

In my project , Each candidate can takepart in some assessments,each assessment has some tests, each test has some questions in it and candidates should answer the questions
at last scores of the questions are saved in question_score and test_score table
I need to get some values of field and use them
I write a method for question_result table, to get them
but i dont know if it is needed to use select_related or not
if it is needed how can i use it ?
Assessment:
class Assessment(BaseModel):
company = models.ForeignKey(
'company.Company',
on_delete=models.CASCADE,
related_name='assessments',
)
title = models.CharField(max_length=255)
job_role = models.ForeignKey(
JobRole,
on_delete=models.PROTECT,
related_name='assessments',
blank=True,
null=True,
)
tests = models.ManyToManyField(
'exam.Test',
related_name='assessments',
blank=True,
through='TestOfAssessment',
)
candidates = models.ManyToManyField(
'user.User',
related_name='taken_assessments',
blank=True,
through='candidate.Candidate'
)
def __str__(self):
return self.title
Test:
class Test(BaseModel):
class DifficultyLevel(models.IntegerChoices):
EASY = 1
MEDIUM = 2
HARD = 3
company = models.ForeignKey(
'company.Company',
on_delete=models.PROTECT,
related_name='tests',
null=True,
blank=True,
)
questions = models.ManyToManyField(
'question.Question',
related_name='tests',
blank=True,
help_text='Standard tests could have multiple questions.',
)
level = models.IntegerField(default=1, choices=DifficultyLevel.choices)
title = models.CharField(max_length=255)
summary = models.TextField()
def __str__(self):
return self.title
Question :
class Question(BaseModel):
company = models.ForeignKey(
'company.Company',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='company_questions',
)
question_text = models.TextField()
def __str__(self):
return truncatewords(self.question_text, 7)
TestResult:
class TestResult(BaseModel):
candidate = models.ForeignKey(
'Candidate',
on_delete=models.CASCADE,
related_name='test_results',
)
test = models.ForeignKey(
'exam.Test',
on_delete=models.CASCADE,
)
test_score = models.DecimalField(default=0.00, max_digits=5, decimal_places=2)
def __str__(self):
return f'{self.candidate.user.email} - {self.test.title}'
Candidate :
class Candidate(BaseModel):
assessment = models.ForeignKey(
'assessment.Assessment',
on_delete=models.CASCADE,
)
user = models.ForeignKey(
'user.User',
on_delete=models.CASCADE,
)
is_rejected = models.BooleanField(default=False)
def __str__(self):
return f'{self.user.email} - {self.assessment.title}'
Company :
class Company(models.Model):
manager = models.ForeignKey('user.User', on_delete=models.CASCADE, related_name='user_companies')
name = models.CharField(max_length=255)
city = models.ForeignKey('company.City', null=True, on_delete=models.SET_NULL)
address = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.name
QuestionResult :
class QuestionResult(BaseModel):
test = models.ForeignKey(
'TestResult',
on_delete=models.CASCADE,
related_name='question_results',
)
question = models.ForeignKey(
'question.Question',
on_delete=models.CASCADE,
related_name='results',
)
result = models.TextField(
null=True,
blank=True,
)
answer_score = models.DecimalField(default=0.00, max_digits=5, decimal_places=2)
def __str__(self):
return f'{self.test.candidate.user.email} - {self.question}'
def text_variables(self):
email = self.test.candidate.user.email
company_name = self.test.test.company.name
assessment_name = self.test.candidate.assessment.title
candidate_first_name = self.test.candidate.user.first_name
job_name = self.test.candidate.assessment.job_role
user_fullname = User.full_name
data = dict(
job_name=job_name,
company_name=company_name,
email=email,
assessment_name=assessment_name,
candidate_first_name=candidate_first_name,
job_name=job_name,
user_fullname = user_fullname
)
return data
I wrote the def text_variables(self): method to fill the data dictionary and use it somewhere else
it work properly but i dont know if it needed to use selected_related or not
something like this (it does not work)
def text_variables(self):
question_result_object = QuestionResult.objects.filter(id=self.id).select_related(
"test__candidate","test__test__company","test__candidate__assessment")
email = question_result_object.test.candidate.user.email
company_name = question_result_object.test.test.company.name
assessment_name = question_result_object.test.candidate.assessment.title
candidate_first_name = question_result_object.test.candidate.user.first_name
job_name = question_result_object.test.candidate.assessment.job_role
data = dict(
job_name=job_name,
company_name=company_name,
email=email,
assessment_name=assessment_name,
candidate_first_name=candidate_first_name,
job_name=job_name,
user_fullname = user_fullname
)
return data
the error is :
File "E:\work\puzzlelity\talent-backend\candidate\models.py", line 385, in report_to_candidate_email_text_variables
email = question_result_object.test.candidate.user.email
AttributeError: 'QuerySet' object has no attribute 'test'
[03/Jan/2023 17:59:00] "POST /api/v1/candidatures/183f8432-ea81-4099-b211-3b0e6475ffab/submit-answer/ HTTP/1.1" 500 123319
I dont know how should i use the select_related
It's never required. It optimizes querysets, especially in ListViews.
Consider your Assessment model. It has ForeignKey fields company and job_role. If you simply fetch
assessment = Assessment.objects.get( id=something)
and then refer to assessment.company, that causes a second DB query to fetch the company object. And then a third if you refer to assessment.job_role.
You can reduce these three queries to one by using
assessment = Assessment.objects.select_related(
'company', 'job_role') .get( id=something)
which does a more complex query to retrieve all the data.
Where it matters is in a list view where you iterate over a large number of assessment objects in Python or in a template. For example, if object_list is assessment.objects.all() and there are 300 of them, then
{% for assessment in object_list %}
... stuff ...
{{assessment.company.name }}
...
{% endfor %}
Will hit the DB 300 times, once for each company! If you use select_related, all 300 companies linked to the 300 assessments will be retrieved in a single DB query. which will be very noticeably faster.
I'd strongly recommend installing Django Debug Toolbar in your development project. Then click on the SQL option on any view, and you can see what SQL was required, and in particular how many SQL queries were performed and whether there were batches of repetetive queries which mean there's a trivial optimisation to be made.

Django modal autoimplement

Can anyone advise on how to deal with retrieving data from other models in Django? I was able to put information with the name of the company in the form, but after choosing from dropdown, I would like the tax identification number from database to be completed automatically. The problem is both the automatic completion and the binding and extraction of data.
p[1]: https://i.stack.imgur.com/V3TJ7.png
p[2]: https://i.stack.imgur.com/qZYAG.png
Model:
klient_lista = Klient.objects.all().values_list("nazwa_firmy", "nazwa_firmy")
class Faktura(models.Model):
numer = models.CharField(max_length=260, blank=False, null=False, unique=True)
klient = models.CharField(max_length=260, choices=klient_lista)
NIP = models.CharField(max_length=260)
kwota_netto = models.FloatField(blank=False, null=True)
VAT = models.FloatField(blank=False, null=True)
kwota_brutto = models.FloatField(blank=False, null=True)
views:
#login_required
def Faktury(request):
faktura = Faktura.objects.all()
faktura_Form = Faktura_Form(request.POST or None)
if faktura_Form.is_valid():
faktura_Form.save()
return redirect(Faktury)
return render(request, 'Faktury.html', {'form': Faktura_Form, 'faktura': faktura})
You don't need to store klient objects in a variable instead use foreign key to connect the two tables. I hope you refer to the "number" field by tax identification number and it is defined in klient model.
class Faktura(models.Model):
klient = models.ForeignKey(Klient,on_delete=models.CASCADE)
NIP = models.CharField(max_length=260)
kwota_netto = models.FloatField(blank=False, null=True)
VAT = models.FloatField(blank=False, null=True)
kwota_brutto = models.FloatField(blank=False, null=True)
To use client name include following in you client model
class Klient(models.Model):
...model fields
def __str__(self):
return self.name
replace name with the field which stores client name

How to copy a object data to another object in Django?

I am trying to create an E-Commerce Website and I am at the Final Step i.e. Placing the Order. So, I am trying to add all the Cart Items into my Shipment model. But I am getting this error.
'QuerySet' object has no attribute 'product'
Here are my models
class Product(models.Model):
productId = models.AutoField(primary_key=True)
productName = models.CharField(max_length=200)
productDescription = models.CharField(max_length=500)
productRealPrice = models.IntegerField()
productDiscountedPrice = models.IntegerField()
productImage = models.ImageField()
productInformation = RichTextField()
productTotalQty = models.IntegerField()
alias = models.CharField(max_length=200)
url = models.CharField(max_length=200, blank=True, null=True)
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField(max_length=100)
profileImage = models.ImageField(blank=True, null=True, default='profile.png')
phoneNumber = models.CharField(max_length=10, blank=True, null=True)
address = models.CharField(max_length=500, blank=True, null=True)
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
dateOrdered = models.DateTimeField(auto_now_add=True)
orderCompleted = models.BooleanField(default=False)
transactionId = models.AutoField(primary_key=True)
class Cart(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, blank=True, null=True)
quantity = models.IntegerField(default=0, blank=True, null=True)
dateAdded = models.DateTimeField(auto_now_add=True)
class Shipment(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
orderId = models.CharField(max_length=100)
products = models.ManyToManyField(Product)
orderDate = models.CharField(max_length=100)
address = models.CharField(max_length=200)
phoneNumber = models.CharField(max_length=13)
I just removed additional functions i.e. __str__ and others.
Here is the views.py
def orderSuccessful(request):
number = Customer.objects.filter(user=request.user).values('phoneNumber')
fullAddress = Customer.objects.filter(user=request.user).values('address')
timeIn = time.time() * 1000 # convert current time in milliSecond
if request.method == 'POST':
order = Shipment.objects.create(customer=request.user.customer, orderId=timeIn,
orderDate=datetime.datetime.now(), address=fullAddress,
phoneNumber=number)
user = Customer.objects.get(user=request.user)
preOrder = Order.objects.filter(customer=user)
orders = Order.objects.get(customer=request.user.customer, orderCompleted=False)
items = orders.cart_set.all() # Here is all the items of cart
for product in items:
product = Product.objects.filter(productId=items.product.productId) # error is on this line
order.products.add(product)
Cart.objects.filter(order=preOrder).delete()
preOrder.delete()
order.save()
else:
return HttpResponse("Problem in Placing the Order")
context = {
'shipment': Shipment.objects.get(customer=request.user.customer)
}
return render(request, "Amazon/order_success.html", context)
How to resolve this error and all the cart items to field products in Shipment model?
Your model is not really consistent at all. Your Cart object is an m:n (or m2m - ManyToMany) relationship between Product and Order. Usually, you would have a 1:n between Cart and Product (a cart contains one or more products). One Cart might be one Order (unless you would allow more than one carts per order). And a shipment is usually a 1:1 for an order. I do not see any of this relationships in your model.
Draw your model down and illustrate the relations between them first - asking yourself, if it should be a 1:1, 1:n or m:n? The latter can be realized with a "through" model which is necessary if you need attributes like quantities.
In this excample, we have one or more customers placing an order filling a cart with several products in different quantities. The order will also need a shipment fee.
By the way: bear in mind that "filter()" returns a list. If you are filtering on user, which is a one to one to a unique User instance, you would better use "get()" as it returns a single instance.
Putting in into a try - except or using get_object_or_404() makes it more stable.
product = Product.objects.filter(productId=items.product.productId)
should be something like:
product = product.product
not to say, it becomes obsolete.
It looks like you make a cart for a product by multiple instances of Cart, the problem is you try to access the wrong variable, also you don't need to filter again when you already have the instance, make the following changes:
carts = orders.cart_set.all() # Renamed items to carts for clarity
for cart in carts:
product = cart.product
order.products.add(product) # The name order is very misleading makes one think it is an instance of Order, actually it is an instance of Shipment
As mentioned above in my comment your variable names are somewhat misleading, please give names that make sense to any variable.

Django Joining Tables

I am trying to get the information from one table filtered by information from another table (I believe this is called joining tables).
I have these two models:
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.CharField(max_length=500)
price = models.DecimalField(max_digits=11, decimal_places=2, validators=[MinValueValidator(Decimal('0.01'))])
category = models.ForeignKey(Category, on_delete=models.CASCADE, default="")
imageURL = models.URLField(blank=True, max_length=500)
creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name="creator", default="")
isOpen = models.BooleanField(default=True)
def __str__(self):
return f"{self.id} | {self.creator} | {self.title} | {self.price}"
class Watchlist(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="listingWatched", default="")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="userWatching", default="")
What I need to do is to get all the listings from a specific user Watchlist, the idea is to generate a page with all of the information of each of the listings that are in the user's watchlist. What should I do?
Thanks in advance!
Since is a foreign key, in Django you can access the information by calling the attribute
For example:
my_user = Watchlist.objects.get(pk=1)
print(my_user.listing.title)
You can also access to that attrbute in a query in case you need to filter upwards some value
values = Watchlist.objects.all().filter(listing__title='MyTitle')
my_titles = [x.title for x in values]
print(my_titles)
Or in your case, if you want to list all the title for a specific user
values = Watchlist.objects.all().filter(user='foo_user')
my_titles = [x.listing.title for x in values]
print(my_titles)
More documentation here

django-import-export export is slow when there is foreign key

when there is foreign key in model, exporting is very slow, when I exclude the foreign there is no problem, it starts to download quickly. What might be the issue here? Thanks!
My code is like,
resources.py
class InvoiceResource(resources.ModelResource):
class Meta:
model = Invoices
views.py
def export_invoice(request):
person_resource = InvoiceResource()
dataset = person_resource.export()
response = HttpResponse(dataset.xlsx, content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="invoices.xlsx"'
return response
models.py
class Invoices(models.Model):
store_code = models.ForeignKey(MasterData, on_delete=models.CASCADE, db_column='Store Code', blank=True, null=True, verbose_name='Store Code')
erp_id = models.CharField(db_column='ERP ID', max_length=200, blank=True, null=True, verbose_name='ERP ID')
store_name = models.CharField(db_column='Store Name', max_length=200, blank=True, null=True, verbose_name='Store Name')
I think you should use select_related
class ModelA(models.Model):
fk = models.Foreingkey(ModelB)
class ModelB(models.Model):
title = models.CharField(max_lenght=20)
if you use:
a_objects = ModelA.objects.all()
for obj in a_objects:
fk = obj.fk
every object need query to database
but if you use
a_objects = ModelA.objects.all().select_related('fk')
for obj in a_objects:
fk = obj.fk
in this case only one query to database.
For more information go to https://docs.djangoproject.com/en/2.0/ref/models/querysets/
class InvoiceResource(resources.ModelResource):
def get_queryset(self):
return super().get_queryset().select_related('store_code')
class Meta:
model = Invoices