I have 3 models in Django:
Student
Teacher
Publication
A single publication can have multiple authors, who can be both students and teachers. Since a student and teacher can have multiple publications and a publication can have multiple teachers and students as authors, I am using a M2M relationship using a through table called PublicationAuthor. However, I am not sure how to get my authors column in my through table. My effort so far :
from django.db import models
class Student(models.Model):
name = models.CharField(max_length=50)
publication = models.ManyToManyField(Publication, through=PublicationAuthor, related_name='students')
class Teacher(models.Model):
name = models.CharField(max_length=50)
publication = models.ManyToManyField(Publication, through=PublicationAuthor, related_name='students')
class Publication(models.Model):
title = models.CharField(max_length=50)
class PublicationAuthor(models.Model):
publication = models.ForeignKey(Publication, on_delete=models.CASCADE)
authors =
You can do this:
class Publication(models.Model):
title = models.CharField(max_length=50)
student_authors = models.ManyToManyField(Student, related_name='student_authros')
teacher_authors = models.ManyToManyField(Teacher, related_name='teacher_authors')
So that if the publication has no author of some type the field simply remains empty.
Related
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,)
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 using django_filters to create filters.
My models in models.py:
class Person(models.Model):
Name = models.CharField("Name", max_length = 50)
class School(models.Model):
Name = models.CharField("School Name", db_column='Name', max_length=50)
class Person_School(models.Model):
PersonID = models.ForeignKey(Person, models.DO_NOTHING, db_column='PersonID')
SchoolID = models.ForeignKey(School, models.DO_NOTHING, db_column='SchoolID')
The 'Person_School' is an associative table that links 'Person' and 'School'. I want to create a drop down list in front end that contains university names, people's names can be filtered by university names. I only know basic function of django_filters, but have no idea when there is an associative table. How should I code in filters.py using django_filters? Thanks
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