Link to child to parent in Django model - django

I have a Place Model:
class Place(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
country = models.CharField(max_length=100, null=True, blank=True)
postal_code = models.CharField(max_length=100, null=True, blank=True)
region = models.CharField(max_length=1000, choices=REGION, null=True, blank=True)
longitude = models.CharField(max_length=20, null=True, blank=True)
latitude = models.CharField(max_length=20, null=True, blank=True)
date_created = models.DateTimeField(_('date created'), default=timezone.now)
date_modified = models.DateTimeField(_('date_modified'), auto_now=True)
Originally I create place to save information about a city, like San Francisco or New York.
Now I want to create a new model called Bar:
class Bar(Place):
location = models.OneToOneField(Place, verbose_name=_('location'), related_name='bar', blank=True, on_delete=models.PROTECT, parent_link=True)
date_inception = models.DateField(null=True, blank=True)
date_closed = models.DateField(null=True, blank=True)
I would like to link the bar to a particular city in the Place model. So I'm linking one row of the an inherited model with its parent. Can I avoid creating a city model and the Bar should Foreignkey into? Is this doable? If so, how do I do it?

When you set parent_link=True in your OneToOneField, the joined models are treated as the same model when working with the ORM, even though they are two separate database tables.
There is no need to link Bar to a particular Place; you can use the Bar model to create both the Bar instance and the Place instance at the same time:
bar = Bar.objects.create(name='Blackbird', city='San Fransisco',
country='US', date_inception='10-17-2019', ...
)
Based on your comments, I'm guessing you don't want this at all. Instead, you probably want a ForeignKey relationship between Place and the Bar model, since a place (eg San Fransisco) can have many bars, but a bar can only have one place.
Update
From my understanding of your comments, this is what I would suggest:
class PlaceMixin(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
longitude = models.CharField(max_length=20, null=True, blank=True)
latitude = models.CharField(max_length=20, null=True, blank=True)
class Meta:
abstract = True
def save(self, *args, **kwargs):
latitude = self.latitude
longitude = self.longitude
do_stuff(latitude, longitude)
super().save()
class Location(PlaceMixin):
country = models.CharField(max_length=100, null=True, blank=True)
postal_code = models.CharField(max_length=100, null=True, blank=True)
region = models.CharField(max_length=1000, choices=REGION, null=True, blank=True)
class Bar(PlaceMixin):
location = models.ForeignKey(Location, related_name='bars', on_delete=models.CASCADE)
class Store(PlaceMixin):
location = models.ForeignKey(Location, related_name='stores', on_delete=models.CASCADE)
Now you can access both the lat/long of the Place, and of the Location:
>>>location = Location.objects.create(name='San Fransisco', latitude=1, longitude=1)
>>>bar = Bar.objects.create(name='Blackbird', latitude=2, longitude=2, location=location)
>>>
>>>bar.latitude
2
>>>bar.location.latitude
1
To query all bars in San Fransisco:
location = Location.objects.select_related('Bar').get(name='San Fransisco')
bars = location.bars.all()

Related

Creating a Django model ForeignKey field from a specific queryset?

Ok, this is a hard one to explain.
I Have these models:
class Supplier(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
class Product(models.Model):
description = models.CharField(max_length=30)
costprice = models.FloatField(null=True, max_length=99, blank=True)
retailprice = models.FloatField(null=True, max_length=99, blank=True)
barcode = models.CharField(null=True, max_length=99, unique=True, blank=True)
image = DefaultStaticImageField(null=True, blank=True,default='images/item_gC0XXrx.png')
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, null=True, blank=True)
class Order(models.Model):
item = models.ForeignKey(Product, on_delete=models.CASCADE, default='')
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
item_qty = models.IntegerField(null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
My ultimate goal is to be able to create an 'Order' pulling items from a specific supplier.
Now, I have no idea as to make that happen - how do I create an instance of an 'Order',in a form of some sort, that will fetch items from the selected supplier and not all items from everybody else?
You are looking for limit_choices_to

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
}

how to use two instance id of foreign key

I have four models of the shop, customer, product, an order.
I am showing the relation of models
shop
user = models.OneToOneField(User, null=True, related_name='shop', blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=70, null=True, default='shop', )
address = models.CharField(max_length=70, null=True)
Shop_category = models.CharField(max_length=200, null=True, )
customer
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100, null=True, default='customer')
Phone = models.PositiveIntegerField(blank=True, null=True)
product
shop = models.ForeignKey(Shop, models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=100, blank=True)
Brand = models.CharField(max_length=200, blank=True)
description = models.TextField(null=True, blank=True)
order
shop = models.ForeignKey(Shop, models.CASCADE, null=True)
customer = models.ForeignKey(Customer, models.CASCADE, null=True)
product = models.ForeignKey(Product, models.CASCADE, null=True)
quantity = models.CharField(max_length=30)
date_created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=200, choices=STATUS, default='Pending')
note = models.CharField(max_length=1000, null=True)
when customers login then the shop will print on the screen and a button on shop to show the products by the shop in the form card. On the product card, there is an order button that adds the product in order after submitting the selected product will print with the remaining filled of order that shown in the image
how I create order form show that I get the id of shop and product
If you are getting the id of shop and product then you can create order in this way
def your_view_function(request,shop_id,product_id):
customer = request.user.customer
shop = Shop.objects.get(id=shop_id)
product = Product.objects.get(id=product_id)
# assuming you are getting value of quantity and note
quantity = request.POST.get('quantity')
note = request.POST.get('note')
# or you are getting quantity and note from form
order = Order.objects.create(customer=customer,shop=shop,product=product,quantity=quantity,note=note)

Update an instance of a model in django such that the older instance and its relationship with other instances remain unaffected

I have been working on a e-commerce project. I have three models Item, OrderItem, Order. They are linked with Foreignkey(s) (Item -> OrderItem -> Order). Item is the actual product and an Order contain(s) Item(s).
Item basically represents a product. In Item there is an attribute 'price' which needs to updated as need suggest. Like during a sale or something else.
What happens is when I update the price of an Item, the price of that item also gets updated in the instances of the Order(s) that are already completed.
Basically I would want to separate these models in a way such that any changes in the Item model doesn't effect the Orders that are completed.
class Item(models.Model):
title = models.CharField(max_length=100)
sku = models.CharField(max_length=8, validators=[
MinLengthValidator(8)], unique=True)
upc = models.CharField(max_length=12, validators=[
MinLengthValidator(12)], unique=True, blank=True, null=True)
date_updated = models.DateTimeField(
auto_now=True, blank=True, null=True)
price = models.FloatField()
discount_price = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField(upload_to=upload_location, blank=True, null=True)
stock_quantity = models.IntegerField(default=0)
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
item_variations = models.ManyToManyField(ItemVariation)
quantity = models.IntegerField(default=1)
purchase = models.FloatField(blank=True, null=True)
def get_total_item_price(self):
return self.quantity * self.item.price
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
ref_code = models.CharField(
max_length=20, blank=True, null=True, unique=True)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
# Check this
ordered_date = models.DateTimeField()
# When the payment is made it becomes True
ordered = models.BooleanField(default=False)
shipping_address = models.ForeignKey(
'Address', related_name='shipping_address', on_delete=models.SET_NULL, blank=True, null=True)
billing_address = models.ForeignKey(
'Address', related_name='billing_address', on_delete=models.SET_NULL, blank=True, null=True)
payment = models.ForeignKey(
'Payment', on_delete=models.SET_NULL, blank=True, null=True)
coupon = models.ForeignKey(
'Coupon', on_delete=models.SET_NULL, blank=True, null=True)
being_delivered = models.BooleanField(default=False)
received = models.BooleanField(default=False)
refund_requested = models.BooleanField(default=False)
refund_granted = models.BooleanField(default=False)
refund_refused = models.BooleanField(default=False)
Any help will be appreciated, thank you.
You could have ItemPrice as a separate model with a One-to-Many relationship. Which prices for the item are stored with associated date changed.
models.py
class ItemPrice(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
price = models.FloatField()
date_changed = models.DateTimeField(auto_now=True, blank=True, null=True)
Then align your order date with the items price at that current time.

How to achieve dependent foreign keys listing in django-admin?

Suppose I have 3 models:- Address, Country, State
Address Model:
class AddressModel(BaseModel):
country = models.ForeignKey(CountryModel, null=True, blank=True, on_delete=models.PROTECT)
state = models.ForeignKey(StateModel, null=True, blank=True, on_delete=models.PROTECT)
city = models.CharField(max_length=200, null=True, blank=True)
pincode = models.CharField(max_length=6, null=True, blank=True)
address_line_1 = models.TextField(max_length=200, null=True, blank=True)
address_line_2 = models.TextField(max_length=200, null=True, blank=True)
Country Model:
class CountryModel(BaseModel):
name = models.CharField(max_length=100)
code = models.CharField(max_length=30)
and State Model:
class StateModel(BaseModel):
country = models.ForeignKey(CountryModel, on_delete=models.PROTECT)
name = models.CharField(max_length=100)
code = models.CharField(max_length=30)
While adding a new address in django admin, I want to show the list of only those states which belong to the selected country i.e I want to implement something like dependent foreign key list in django-admin.
I would like to achieve it without using jquery or ajax
How can I do that?