Django Models - Reverse Foreign Key - django

These two classes have Foreign Key to each other and class OrderRow is representing a row which belongs to an Order, I want to know is there any way to set "rows" attribute inside class Order to show a list or query-set of all related order rows by calling it on an object or instance of class Order?
class OrderRow(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
order = models.ForeignKey('Order', on_delete=models.CASCADE)
amount = models.IntegerField(default=0)
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
order_time = models.DateTimeField(auto_now_add=True)
total_price = models.IntegerField(null=True, blank=True)
**rows = models.ForeignKey('OrderRow', on_delete=models.CASCADE, related_name='order_rows')**

You should have ForeignKey in OrderRows with related_name="rows". Like this:
class OrderRow(models.Model):
# rest of the fields
order = models.ForeignKey('Order', on_delete=models.CASCADE, related_name='rows')
Then you can use:
order = Order.objects.first()
for order_row in order.rows.all():
print(order_row)
For more information, please check the documentation.

Related

Get foreign key element from a related_name on django

I have three models such as the one below and I am trying to write a query that allows me to access all the Day_Type associated to the Day objects that are pointing to a specific JobProject.
I know that I can get all the Day pointing at a JobProject by querying project.jobproject_days.all() and I can get the values of the Day_Type by doing project.jobproject_days.values_list('day_type__name', flat=True)
BUT how can I get the Day_Type themselves?
class JobProject(models.Model):
......
class Day_Type(models.Model):
name = models.CharField(max_length=30)
class Day(models.Model):
....
day_type = models.ForeignKey(Day_Type, blank=True, on_delete=models.CASCADE, null=True, related_name='day_type')
project = models.ForeignKey(JobProject, blank=True, on_delete=models.CASCADE, related_name='jobproject_days', null=True)
You can fetch it like this:
daytypes = Day_Type.objects.filter(day_type__project=project)

Keep relationships between many-to-many fields django-tables2

I'm working on the development of a web with Django and PostgreSQL and I'm using the app django-tables2 to create HTML tables.
class SampleTable(ColumnShiftTableBootstrap4):
class Meta:
model = Sample
fields = ("name", "sample_id_sex", "pools", "indexes", "gene_cand_lists",)
My database collects Next Generation Sequencing (NGS) data. sample_id_sex is a foreign key (1:N relationship) while pools, indexes and gene_cand_lists are many-to-many fields, the combination of these three rows are unique: in other words, they are related.
My problem is that in each row the values are ordered by default. For example, the sample X belongs to the pool CES001 and has the index B2 and the gene list list3 but it also belongs to the pool CES002 with the index A1 and list1. In the table, they should appear like this (, as the separator in the many-to-many columns):
sample
sex
pools
indexes
gene_lists
12-009
male
CES001, CES002
B2, A1
list3, list1
But they appear like this:
sample
sex
pools
indexes
gene_lists
12-009
male
CES001, CES002
A1, B2
list1, list3
The relationships between the three fields are broken. Is there a way to correct this? And the separator could be a newline and not a comma?
Edit: I think the question is not clear enough. The model of the sample table is:
class Sample(models.Model):
id_sample = models.AutoField(primary_key=True)
name = models.CharField(unique=True, max_length=20)
indexes = models.ManyToManyField(Index, through='SamplePoolIndexCand', blank=True)
pools = models.ManyToManyField(Index, through='SamplePoolIndexCand', blank=True)
gene_lists = models.ManyToManyField(Index, through='SamplePoolIndexCand', blank=True)
And the intermediate table:
class SamplePoolIndexCand(models.Model):
sample_id = models.ForeignKey(Sample, null=True, blank=True, on_delete=models.CASCADE, db_column='id_sample',
verbose_name='Mostra')
pool_id = models.ForeignKey(Pool, null=True, blank=True, on_delete=models.CASCADE, db_column='id_pool',
verbose_name='Pool')
index_id = models.ForeignKey(Index, null=True, blank=True, on_delete=models.CASCADE,
db_column='id_index', verbose_name='Índex')
gene_cand_list_id = models.ForeignKey(GeneCandList, null=True, blank=True, on_delete=models.CASCADE,
db_column='id_gene_cand_list', verbose_name='Llista de gens candidats')
You can use ordering tag in your models particular class of many to many fields
class gene_lists(models.Model):
priority = models.PositiveSmallIntegerField(default=16383)
class indexes(models.Model):
contents = models.ManyToManyField(gene_lists, blank=True, null=True)
class Meta:
ordering = ['priority', 'contents']

Querying using related field names

I've got two models that I'd like to perform a reverse search on. I'm wondering how to do this given the fact that one model has to fields with foreign keys to the same model.
class Review(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, default=None)
class Cart(models.Model):
cost = models.DecimalField(max_digits=50, decimal_places=2, null=True, blank=True)
class Job(models.Model):
cart = models.ForeignKey(Cart, related_name="cart_one", on_delete=models.CASCADE, null=True, blank=True)
unscheduled_job = models.ForeignKey(Cart, related_name="cart_two", on_delete=models.CASCADE, null=True, blank=True)
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, null=True, blank=True)
My query is as follows:
reviews = Review.objects.filter(cart__job__employee=employee)
This query is failing due to the fact that the Job model has two foreign keys that point to the cart model. How would I fix this?
Thanks!
If you specify a related_query_name=… parameter [Django-doc] or a **related_name=… parameter [Django-doc], then that is the name to access the model in reverse, so you can query with:
Review.objects.filter(cart__cart_one__employee=employee)
or if you want to query in reverse with the unscheduled_job, then it is:
Review.objects.filter(cart__cart_two__employee=employee)
You can also combine the two, so bo5th cart anfd unscheduled_job by making use of a Q object:
from django.db.models import Q
Review.objects.filter(Q(cart__cart_one__employee=employee) | Q(cart__cart_two__employee))
You might however want to change the related_name=…s, since this should be the name to access the Job object from the perspective of a Cart model.

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.

QuesrySet eror in django

I have some models:
class OrdersTrigger(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
order_trigger = models.ForeignKey(Order, related_name='trigger', on_delete=models.CASCADE)
....
created_at = models.DateTimeField(auto_now_add=True)
class Order(models.Model):
from_bank = models.ForeignKey(Bank, on_delete=models.CASCADE)
to_bank = models.ForeignKey(Bank, related_name='to', on_delete=models.CASCADE)
I'm getting list of orders from this model using filters :
orders = OrdersTrigger.objects.filter(Q(order__from_bank_=baseBank) & Q(order__to_bank=quoteBank))\
.filter(created_at__gte=latest_time).order_by('-created_at')
when i try to iterates through the list:
for order in orders:
or
for order in orders.all():
I'm receiving an error:
The QuerySet value for an exact lookup must be limited to one result
using slicing.
Can you help me with this? I can not understand how to fix this error.