django: join two tables without foreignkey - django

I have two models which I want to join but they don't have any foreignkey
class Invoice(models.Model):
invoice_id = models.IntegerField(blank=True, null=True)
quotation_id = models.IntegerField(blank=True, null=True)
client_id = models.ForeignKey(tbl_customer, on_delete=models.CASCADE)
invoice_number = models.IntegerField(blank=True, null=True)
quotation_number = models.IntegerField(blank=True, null=True)
date = models.DateField(blank=True, null=True)
total_amount = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
total_tax = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
document_type = models.CharField(max_length=50, default='', blank=True, null=True)
and
class Invoice_Description(models.Model):
invoice_id = models.IntegerField(blank=True, null=True)
client_id = models.ForeignKey(tbl_customer, on_delete=models.CASCADE)
quotation_id = models.IntegerField(blank=True, null=True)
item_id = models.ForeignKey(tbl_item, on_delete=models.CASCADE)
item_qty = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
item_unit_price = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
Invoice contains information about the invoice document, its total price, date, etc while Invoice_Description keeps the records of items added on that particular invoice, item price, total quantity, discount on each item, etc.
I want to display all the records in reports with respect to items like
ITEM NAME CUSTOMER NAME INV. NO. QTY DOCUMENT TYPE UNIT PRICE SALE PRICE
Item1 Client1 01 950.00 1000.00
I have all the columns available from Invoice_Description except for the INV. NO. and DOCUMENT TYPE which are in the Invoice model.
I don't want to use a ForeignKey in this case because these models are already in use in many places, changing the database will require changes everywhere.
my problem is just that I want to join two models in Django but without ForeignKey so that I may get Invoice No. and Document Type of the corresponding row.
Any ideas on how can I do this??

If all you want to do is retrieve an InvoiceDescription object that belongs to a given Invoice, you could do the following:
invoice = Invoice.objects.first()
try:
description = InvoiceDescription.objects.get(invoice_id=invoice.invoice_id)
except InvoiceDescription.DoesNotExist:
description = None
I am assuming that the field invoice_id refers to the invoice ID. Although you didn't declare it using models.ForeignKey, it still acts as a foreign key in this situation. You just have to do the lookup manually.

Related

How to get data from two table through one query Django

** I just need one more table join in my query **
I want to get sales of logged-in users with order detail and shipping address.
I am getting sales of current user through this query but i also want get shipping address.
orderitems = OrderItem.objects.filter(
product__user=request.user, order__complete=1).order_by('-date_orderd')
Now i want to get also address, city and state from the Shippingaddress model.
I attached the models below.
this is my current result.
My models:
Order Model:
class Order(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
date_orderd = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False, null=True, blank=False)
transaction_id = models.CharField(max_length=200, null=True)
# product = models.ManyToManyField(OrderItem)
def __str__(self):
return str(self.id)
Order items Model:
class OrderItem(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, blank=True, null=True)
order = models.ForeignKey(
Order, on_delete=models.SET_NULL, blank=True, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_orderd = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True)
price = models.FloatField(blank=True, null=True)
def __str__(self):
return str(self.product)
Shipping Address Model:
class ShippingAddress(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
order = models.ForeignKey(
Order, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=150)
address = models.CharField(max_length=150)
city = models.CharField(max_length=150)
state = models.CharField(max_length=150)
zipcode = models.CharField(max_length=150)
date_orderd = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
What you are looking for is "Select from multiple tables in one query with Django". You can take a look at the answers here.
Why not add another query like the one below
shp_address = ShippingAddress.objects.filter(product__user=request.user)
and if needed send to the client side as part of context, see below
context = {
'orderitems': orderitems,
'shp_address': shp_address
}

Django loop through a form multiple choice field

I am very new to django and I'm making a project that tracks medications in our drug safe. Part of our daily activities is to check the amount of each drug in the safe and document each amount. In my model for the safe, I have a field "drug_name" that is a foreign key to a list of medications. I want to make a model form that auto populates each choice in the field and asks for the amount of the drug in the safe. Something like:
Drug Name 1
Amount:_________
Drug Name 2
Amount:_________
and so on.
Here is my model
class Safe(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
date_created = models.DateTimeField(auto_now=True)
drug_name = models.ForeignKey('components.Drug', related_name='drug_remove', on_delete=models.PROTECT, default=0, limit_choices_to={'is_active': True})
amount_removed = models.IntegerField(blank=True, null=True)
amount_added = models.IntegerField(blank=True, null=True)
amount_in_safe = models.IntegerField(blank=True, null=True)
incident_number = models.CharField(max_length=20, default=0, blank=True)
patient_name = models.CharField(max_length=20, default=0, blank=True)
medic_unit = models.ForeignKey('components.MedicUnit', related_name='medic_unit', on_delete=models.PROTECT, blank=True, null=True)
free_text = models.CharField(max_length=1000, default=0, blank =True)
I'm not sure if I could submit all at once or if I would have to submit one drug at a time. Either way would work well as long as the user didn't have to manually select each medication. Thanks ahead of time for any help.

Show two tables specific column data into one list?

I have two tables Customer and Subscription in which Customer has the list of customers and Subscription contains the Customer and Packages.
In the customer list i want to show how many packages each customer has.
Subscription Model
class Subscription(models.Model):
client = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True, related_name="subscriptions")
package = models.ForeignKey(Package, on_delete=models.SET_NULL, blank=True, null=True)
valid_start_date = models.DateTimeField()
valid_end_date = models.DateTimeField()
usage_count = models.IntegerField(null=True)
status = models.CharField(max_length=20)
transaction = models.BigIntegerField(blank=True, null=True, default=0)
created_at = models.DateTimeField()
updated_at = models.DateTimeField()
Customer Model
class Customer(AbstractBaseUser):
first_name = models.CharField(max_length=250, blank=True, null=True)
last_name = models.CharField(max_length=250, blank=True, null=True)
email = models.EmailField(unique=True, blank=True, null=True)
mobile_number = models.BigIntegerField(blank=True, null=True)
password = models.CharField(max_length=1000, blank=True, null=True)
gender = models.CharField(max_length=10, blank=True, null=True)
profile_picture = models.ImageField(upload_to="user_data/profile_picture", blank=True)
address = models.CharField(max_length=500, blank=True, null=True)
country = models.ForeignKey(Countries, on_delete=models.SET_NULL, blank=True, null=True)
state = models.ForeignKey(States, on_delete=models.SET_NULL, blank=True, null=True)
city = models.ForeignKey(Cities, on_delete=models.SET_NULL, blank=True, null=True)
pincode = models.IntegerField(blank=True, null=True)
number_of_logins = models.IntegerField(blank=True, null=True)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
USERNAME_FIELD = "email"
Expected Result : I want to show the package field data from Subscription Model into the list of Customer model.
name - no. - emaiId- pakages_subbed
customer1 - mobile - email - package1,package2
customer2 - mobile - email - package4,package1
Actual Result : Only Customer field data
You need to use annotate in your queryset much as here
I think
query = Customer.objects.annotate(subscription_count=Count('subscriptions'))
ought to do it (with the count available as object.subscription_count for any object retrieved from this query)
This is just one database query, returning only Customer objects, whereas {{ customer.subscriptions.all|length }} will be a lot of them (and will probably also retrieve all the Subscription objects just to count them).
If you wanted greater access to the Subscription and Package objects you could do
Subscription.objects.all().order_by("client__id", "package__name")...
(I made up "package__name") which should get you the subscriptions grouped firstly by customer and then ordered by package name for each customer.

Django QuerySet, Filtering Data Based on The Latest Entry of Each Data's Column/Field equals to a particular Value

#models.py
class Orders(models.Model):
orderid = models.IntegerField(db_column='orderID', primary_key=True)
createdate = models.DateField(db_column='createDate', blank=True, null=True)
pickupdate = models.DateField(db_column='pickupDate', blank=True, null=True)
returndate = models.DateField(db_column='returnDate', blank=True, null=True)
pickupstore = models.ForeignKey(Branch, models.DO_NOTHING, db_column='pickupStore', blank=True, null=True,related_name = 'pickupstore')
returnstore = models.ForeignKey(Branch, models.DO_NOTHING, db_column='returnStore', blank=True, null=True,related_name = 'returnstore')
rentedvehicle = models.ForeignKey('Vehicles', models.DO_NOTHING, db_column='rentedVehicle', blank=True, null=True)
customer = models.ForeignKey(Customer, models.DO_NOTHING, db_column='customer', blank=True, null=True)
class Vehicles(models.Model):
vehicleid = models.IntegerField(db_column='vehicleID', primary_key=True)
make = models.CharField(max_length=45, blank=True, null=True)
model = models.CharField(max_length=45, blank=True, null=True)
series = models.CharField(max_length=45, blank=True, null=True)
Orders model have foreign key rentedvehicle which refers to Vehicles models
I have filtered the data based on the pickupstore state, e.g. The list of vehicles that are picked up from store in a particular state
Vehicles.objects.filter(orders__pickupstore__state = request.POST['state'])
I want to be able to filter the filtered data above so that I can get a list of vehicles that are picked up from store in a particular state WITH its latest entry in Orders models has returnstore__state == a particular state
So basically, I want to achieve this:
Vehicles.objects.filter(orders__pickupstore__state = request.POST['state']).filter(the latest entry returnstore state =request.POST['state'])
Many possible solutions. Optimal depends on your Django version (1.11 or higher?). Here's one possible solution:
from django.db.models import Max, F
Vehicles.objects.filter(orders__pickupstore__state = request.POST['state']).annotate(max_date=Max('orders__returndate')).filter(orders__return_date=F('max_date')).filter(orders__state = request.POST['state'])
What's happening here is that we're identifying the most recent return date, then filtering the orders to only include the most recent, then filtering the Vehicles on the state of that latest order.

django admin foreign key default value inline

I'm converting an ancient Client/Server app (Delphi) into a Django app for a small brick and morter bookstore (wife's).
Since most functions are admin, I'm using the Django admin interface with grappelli for some easier lookups.
I have 3 models: Book, Sale and Item.
class Book(TimeStampedModel):
"""
Books are described individually and are related to collections
as many to many. Every book in this system is unique - i.e. there are
not quantity fields. This is optimized for used book stores where book
condition is essential.
"""
STATUS_CHOICES = (
('IN STOCK', 'IN STOCK'),
('SOLD', 'SOLD'),
('ON LOAN', 'ON LOAN'),
('HOLD', 'HOLD'),
)
isbn = models.CharField(max_length=50, blank=True)
title = models.CharField(max_length=200, blank=False, db_index=True)
author = models.CharField(max_length=200, blank=True)
sell_price = models.DecimalField(max_digits=10,decimal_places=2, default=0)
description = models.TextField()
collections = models.ManyToManyField(Collection)
class Meta:
index_together = [
["author", "title"],
["status", "title", "author"],
]
def __unicode__(self):
return "%s [%d] - %s - $%.2f" % (self.title, self.id, self.book_type, self.sell_price)
#staticmethod
def autocomplete_queryset():
instock = Book.objects.filter(status="IN STOCK")
return instock
#staticmethod
def autocomplete_search_fields():
return("id__iexact", "title__istartswith",)
class Sale(TimeStampedModel):
"""
Sales group all sold items which may or may not be books and are sold to contacts.
We use a "generic" contact of "cash" for non named contacts
"""
PAYMENT_TYPE_CHOICES = ( ('Cash', 'Cash'), ('Charge', 'Charge'), ('Check', 'Check'))
contact = models.ForeignKey(Contact, null=True)
sale_date = models.DateField(blank=True,default=datetime.date.today, db_index=True)
payment_type = models.CharField(max_length=50, choices=PAYMENT_TYPE_CHOICES)
taxed = models.BooleanField(default=True)
tax_exempt_no = models.CharField(blank=True, max_length=50)
sales_tax = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
amt_tender = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
pct_discount = models.SmallIntegerField(blank=True, null=True)
amt_credit = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
amt_shipping = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
amt_due = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
tot_sale = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
tot_items = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
ordering = ['-sale_date']
def __unicode__(self):
return str(self.sale_date)
class Item(TimeStampedModel):
"""
Items are usually books sold on a sale. Items can also be entered manually
at time of sale if they are not books from inventory
"""
sale = models.ForeignKey(Sale)
book = models.ForeignKey(Book, null=True, blank=True)
item_desc = models.CharField(blank=True, max_length=200)
cost = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
sell_price = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
def __unicode__(self):
return self.item_desc
For the Sale form, I use an admin form with Tabular inline Items. Items are usually books (via a foreign key lookup), but can also be entered manually for non-inventory items so I have a sell_price both in the book model and in the item model.
class ItemInline(admin.TabularInline):
model = Item
raw_id_fields = ("book",)
autocomplete_lookup_fields = {
'fk': ['book'],
}
extra = 2
What I'd like to do in the foreign key lookup is to return the key of the book AND fill in the Item's sellprice with the sellprice from the book I looked up.
I have the basic lookup working just fine but can't find out how to set the item sellprice to the book's sellprice immediately after the lookup.
Any advice is appreciated! I have tried figuring out the objects to put some JS logic in but the inlines get object ids created dynamically, I think. I'm no JS expert.