I have a product model with name, description, currency, price, vendor and image fields, and I'm trying to implement ordering items, and I'm having a bit of trouble doing that.
Basically, what I want is to be able to access an Orders model in the admin and add an order number, customer name (I have already implemented these two), and some products with each product having a quantity.
# models.py
from django.db import models
class Vendor(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Product(models.Model):
currencies = [
('$', "US Dollars ($)"),
]
name = models.CharField(max_length=40)
description = models.TextField()
currency = models.CharField(max_length=5, choices=currencies, default="$")
price = models.DecimalField(max_digits=10, decimal_places=2)
vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE)
image = models.ImageField(default="not_found.jpg")
def __str__(self):
return self.name
class Customer(models.Model):
name = models.CharField(max_length=30)
date_of_birth = models.DateField()
def __str__(self):
return self.name
class Order(models.Model):
order_number = models.CharField(max_length=20)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
My attempts/solutions:
Adding ManyToManyField to Product (No Quantity)
Creating ProductInstance class with fk to product and order (Quantity added but You have to visit 2 different pages in the admin, and you can't see the items in orders page of admin)
Are there any other ways I can implement this or am I stuck with the second solution? It wouldn't be awful to do this but I rather avoid it and have the ability to add items on the orders page
I'm sorry if I sound like a beggar. I'm really not but I can't form nice-sounding sentences
Edit: I found what I needed!
Using the second solution I mentioned, I created a class called ProductInstance, and later renamed it to OrderProduct, made the following fields:
ForeignKey to Products
ForeignKey to Orders
IntegerField for quantity
The order class had the following fields:
CharField for order number
ForeignKey for customer
ManyToMany to product through OrderProduct
Then, I added the following in admin.py:
# admin.py
...
class OrderInlines(admin.TabularInline):
model = OrderProduct
fk_name = "order"
extra = 1
#admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
fields = ('order_number', "customer",)
inlines = (OrderInlines,)
Related
I have these models (simplified):
class Product(TimeStampedModel):
product_id = models.AutoField(primary_key=True, )
shop = models.ForeignKey('Shop', related_name='products', to_field='shop_name', on_delete=models.CASCADE)
category = models.ForeignKey('Category', related_name='products', to_field='category_name', on_delete=models.SET_NULL)
brand = models.ForeignKey('Brand', related_name='products', to_field='brand_name', on_delete=models.CASCADE)
class Brand(models.Model):
brand_name = models.CharField(max_length=50)
shops = models.ManyToManyField('Shop', related_name='shops')
categories = models.ManyToManyField('Category', related_name='categories')
class Category(models.Model):
category_name = models.CharField(max_length=128)
shops = models.ManyToManyField('Shop')
class Shop(models.Model):
shop_name = models.CharField(max_length=30)
In admin I am trying manually to change a Category for bunch of selected Products (I have a custom function for that). But here I see 2 problems:
1) Must be updated M2M relation in Brand->Category, if there was no Brand with this Category.
2) Must be updated M2M relation in Category->Shop, if there was not this selected Category in the Shop.
How to do this in the best way? I know that this might be some kind of Django signals use, specially m2m_changed, but I can't understand who is emitter of the signal, and who is receiver, and how to update multiple tables after change in 1 table.
I am trying to create the proper Django model that could fit the following reqs:
Person Class has 1 to many relations with the Address Class
Person Class has many to many relations with the Group Class
Book Class contains the collections of the Persons and the Groups
This is my code:
class Person(models.Model):
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=20)
def __str__(self):
return self.first_name+ ' - ' + self.last_name
class Address(models.Model):
person = models.ForeignKey(Person)
address_line = models.CharField(max_length=200)
def __str__(self):
return self.address_line
class Group(models.Model):
group_name = models.CharField(max_length=12)
persons = models.ManyToManyField(Person)
def __str__(self):
return self.group_name
class Book(models.Model):
record_name = models.CharField(max_length=12)
person = models.ForeignKey(Person )
group = models.ForeignKey(Group )
def __str__(self):
return self.record_name
However it's not correct:
1) A Group can now contain multiple Persons but the Persons do not contain any Group.
I am not sure if I should add to the Person class the following code:
groups = models.ManyToManyField(Group)
2) The Book class now contains only 1 record of Person & Group per Book record.
3) When I added the Foreign Keys to the models, I removed
on_delete tag:
person = models.ForeignKey(Person, on_delete=models.CASCADE())
because it does not compile it, asking for some params.
I know how to make all this for C#, but I am a kinda stucked with this simple task in Python/Django.
1) The ManyToMany field should appear only in one of the models, and by looks of things you probably want it in the Person model.
Its important to understand that the data about the ManyToMany field is saved in a differant table. Django only allows this field to be visable through buth models (so basiclly, choose where it is move convinient).
2)By the look of your structure I will suggest you use a ManyToMany field through a different table. here is an example:
class Activity(models.Model):
name = models.CharField(max_length=140)
description = models.TextField(blank=True, null=True)
class Route(models.Model):
title = models.CharField(max_length=140)
description = models.TextField()
activities_meta = models.ManyToManyField(Activity, through = 'RouteOrdering')
class RouteOrdering(models.Model):
route = models.ForeignKey(Route, on_delete=models.CASCADE)
activity = models.ForeignKey(Activity, on_delete=models.CASCADE, related_name='activita')
day = models.IntegerField()
order = models.IntegerField(default=0)
that way the data is binded to the ManyToMany field
Below is my Django models code
from django.db import models
class BookUser(models.Model):
email= models.CharField(max_length=254,primary_key=True) #mail address key
name = models.CharField(max_length=254) #max 64 char (lower case?)
contact= models.CharField(max_length=12)
imei = models.CharField(max_length=16) #imei number
address= models.TextField() #list of address ids
booksInShelf:[] #list of user book's unique ids
booksUnderCirculation:[] #list of user book's unique ids
class Meta:
ordering = ('email',)
class Book(models.Model):
isbn = models.CharField(max_length=13)
title=models.CharField(max_length=500)
description =models.TextField()
author = models.CharField(max_length=200)
userRating = models.CharField(max_length=1)
users = #list of user ids hold this book in shelf
class UserBook(models.Model):
#id: generated by django
bookId: #id of parent book
rent= models.BooleanField(default=False) #boolean is ready to rent
sell= models.BooleanField(default=False) #boolean is ready to sell
price =models.FloatField() #selling price
rentBase=models.FloatField() #base price of rent
rentPeriod=models.IntegerField() #days after which extra rent would apply
dateModified =models.DateTimeField(auto_now=True) #track date it came into shelf
dateAdded = models.DateTimeField(auto_now_add=True)
Here BookUser is the actual user who has some books in two categories i.e booksinShelf and bookUnderCirculation
class Book is central repository of all books, I need to define a one to many relation to BookUser.What is the easy way to do this?
User Book is specific to BookUser and it should be uniquely pointing to Class Book , So its many to one relation to Book Class.
I am confused on how to handle ids of UserBook and Book?
Also how to store the list of ids of UserBooks in class BookUser??
After looking at the Models and explanation provided below the Book model the users field should have ForeignKey relationship with the BookUser model.
so Book model should look like
class Book(models.Model):
isbn = models.CharField(max_length=13)
title=models.CharField(max_length=500)
description =models.TextField()
author = models.CharField(max_length=200)
userRating = models.CharField(max_length=1)
users = models.ForeignKey(BookUser, null=True, blank=True)
if you are using Postgresql and if you just need the pk list of booksInShelf and booksUnderCirculation then your BookUser model should look like
class BookUser(models.Model):
email= models.CharField(max_length=254,primary_key=True)
name = models.CharField(max_length=254)
contact= models.CharField(max_length=12)
imei = models.CharField(max_length=16)
address= models.TextField()
booksInShelf = models.ArrayField(models.IntegerField())
booksUnderCirculation = models.ArrayField(models.IntegerField())
and if you wish to have the full information of booksInShelf and booksUnderCirculation (not just the pk but other information related to the book as well), then you need to define it as ManyToMany relation.
class BookUser(models.Model):
email= models.CharField(max_length=254,primary_key=True)
name = models.CharField(max_length=254)
contact= models.CharField(max_length=12)
imei = models.CharField(max_length=16)
address= models.TextField()
booksInShelf = models.ManyToMany(UserBook)
booksUnderCirculation = models.ManyToMany(UserBook)
also rather than creating two ManyToMany fields in the BookUser model you can have two flags in your UserBook model called is_in_shelf and is_under_circulation. These fields would be BooleanField, you can check more about the model fields in Django Documentation here: https://docs.djangoproject.com/en/1.10/topics/db/models/#fields
This should do what you want :
class UserBook(models.Model):
bookId = models.ForeignKey('Book')
Here a UserBook has a reference to a Book item, and severals users can have the same book, but it's still a unique reference in you table Book.
Hope it helps
I have a polling app with one of the models "Choice" consisting of 2 Foreign key fields linked to the "Person" model.
I wanted to automatically populate related "photo_other" field (with the image link) once I have selected the "name" of the person. "name" is also a Foreign Key Field linked with Choice model.
models.py
class Choice(models.Model):
name = models.ForeignKey(Person)
photo_other = models.ForeignKey(Person)
rating = models.DateTimeField(blank=True, null=True)
def __unicode__(self):
return smart_unicode(self.name)
class Person(models.Model):
name = models.CharField(max_length=250)
photo = models.ImageField(upload_to="photos")
pub_date = models.DateTimeField()
def __unicode__(self):
return smart_unicode(self.name)
Why do you want to store the same value in two different tables when they are connected through a foreign key? It just doesn't make sense.
class Choice(models.Model):
name = models.ForeignKey(Person)
rating = models.DateTimeField(blank=True, null=True)
#property
def photo_other(self):
return self.name.photo
class Person(models.Model):
name = models.CharField(max_length=250)
photo = models.ImageField(upload_to="photos")
pub_date = models.DateTimeField()
In order to make photo_other visible under the admin page of Choice model, you can do the following;
class ChoiceAdmin(admin.ModelAdmin):
list_display = ['name', 'rating', 'get_photo']
def get_photo(self, obj):
return obj.photo_other
get_photo.short_description = 'Photo'
My model's ER diagram in here
This is part of my models.py.
class Company(models.Model):
user = models.OneToOneField(User)
company_id = models.AutoField(primary_key=True)
...
class Store(models.Model):
store_id = models.AutoField(primary_key=True)
store_company = models.ForeignKey('Company', related_name='storecompany')
store_city = models.ForeignKey('City', related_name='cities', to_field='city_name')
...
class Discount(models.Model):
discount_id = models.AutoField(primary_key=True)
discount_category = models.ManyToManyField(Category, related_name="discountcategory")
discount_store = models.ManyToManyField(Store, related_name="discountstores")
...
class City(models.Model):
city_name = models.CharField(primary_key=True, max_length=25)
class Category(models.Model):
category_id = models.AutoField(primary_key=True)
category_name = models.CharField(max_length=50)
I want to filter discounts with their city. All discounts have a city. For example I received some city name, "bursa" in "city" variable. And I want to filter all discounts in "bursa" city. Maybe my model isn't right but I don't know.
I tried a lot of filter but I couldn't.
First, in your class Store, the related_name is not "correct", it should be something like "stores" not "cities" because related_name attribute specifies the name of the reverse relation from the City model back to your model.
Less assume that you changed it.
class Store(models.Model):
store_id = models.AutoField(primary_key=True)
store_company = models.ForeignKey('Company', related_name='storecompany')
store_city = models.ForeignKey('City', related_name='stores', to_field='city_name')
Then, given a city name
your_city = City.objects.filter(city_name='city_name')[0]
stores = your_city.stores.all()
discounts = [store.discountstores.all() for store in stores]
Always start from the model you actually want to get. If you want Discounts, query that model, using the double underscore syntax to traverse relationships.
Discount.objects.filter(discount_store__store_city__city_name="bursa")