django models.py - migrating from one model class to another - python

I am trying to break up an existing model class. The original class is not optimal so I want to move all customer relevant information from CustomerOrder into a new class Customer. What is the best way to do this in Django?
Old model class:
class CustomerOrder(models.Model):
# Customer information fields
first_name = models.CharField(max_length=200) # Customer first name
last_name = models.CharField(max_length=200) # Customer last name
email = models.EmailField() # Customer email address
address = models.CharField(max_length=255) # Address to deliver (e.g. 1532 Commonwealth St. Apt 302)
city = models.CharField(max_length=200) # City to deliver (e.g. Fullerton, CA 92014)
# Order information fields
note = models.TextField() # Any notes the customer may have about shipping
shipping_method = models.CharField(max_length=200) # Shipping in LA or OC
total_price = models.FloatField(default=0) # Total price of the order
delivery_date = models.DateField() # When to deliver the order. Order is "live" until the next
# day after delivery. So if delivery date is Jan 3, it's "live" until Jan 4.
order_date = models.DateField() # When the customer ordered
time_slot = models.CharField(max_length=200) # What time to deliver the product
is_cancelled = models.BooleanField(default=False) # If the order is cancelled or refunded, we mark it here.
created_at = models.DateTimeField(auto_now_add=True) # When the order entry was saved into database
updated_at = models.DateTimeField(auto_now=True) # When the order was last updated in database
def __str__(self):
return self.first_name + " " + self.last_name
New model class:
class Customer(models.Model):
first_name = models.CharField(max_length=200) # Customer first name
last_name = models.CharField(max_length=200) # Customer last name
email = models.EmailField() # Customer email address
address = models.CharField(max_length=255) # Address to deliver (e.g. 1532 Commonwealth St. Apt 302)
city = models.CharField(max_length=200) # City to deliver (e.g. Fullerton, CA 92014)
There are duplicates in the old model so i want to remove those as well.

It depends on your database type. read this
You should be careful to dont loose your data!

I think the question is more to do with the whole relational database schema.
I would have all customer related stuff in one table just like the new CustomerOrder (rename this to Customer) class you have, then create another class for Orders then link the two with a one to many relationship. For example one customer can place many orders. If you want to implement this one to many relationship, simply add the following to the order class:
class Order(models.Model):
# The relavant order fields which you require, i.e. order number etc.
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
Now when you create a new order instance, you can assign the customer.
p.s. to access in reverse i.e. from customer to order you basically do customer.order_set() method (Customer can place many orders).

Related

How to increment a serial number in Django model with order by created_at

I'm developing a hospital project!
People can apply online appointment for a specific doctor and the people will get a serial number once done the process of online appointment.
Here is my model:
class Appointment(models.Model):
doctor = models.ForeignKey(
DoctApp, on_delete=models.CASCADE, related_name="appointments")
fee = models.IntegerField(default=1000, validators=[
MaxValueValidator(2000)])
name = models.CharField(max_length=220)
phone = models.CharField(max_length=12, default="01700000000")
age = models.IntegerField(validators=[MaxValueValidator(200)])
gender = models.CharField(max_length=10, choices=gen_choises)
address = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
pat_pic_date = models.DateField()
serial_number = models.IntegerField()
def __str__(self) -> str:
return f"""ID: {self.doctor.id} - {self.doctor.name} - Pat Name: {self.name}"""
Can you consider to share the auto-increment fields system to get serial the number fields?
It sounds like you're looking for the primary key of the newly created appointment record. If so, you should be able to retrieve that with self.id
If you'd like to modify that number, here are some examples of how that could be done:
https://stackoverflow.com/a/16753988/1536402

How can I organize a database with products and users?

I am currently trying to organize a django database model for an online shop-system with users and products.
My code:
class UserData(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=500)
bought_products = models.ForeignKey(MarketProducts, on_delete=models.CASCADE)
class VendorData(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=500)
sold_products = models.ForeignKey(MarketProducts, on_delete=models.CASCADE)
class MarketProducts(models.Model):
category = models.CharField(max_length=100)
vendor = models.ForeignKey(VendorData, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
description = models.CharField(max_length=1000)
price = models.IntegerField()
pub_date = models.DateTimeField('Date published')
image = models.ImageField(upload_to=b'shop/media/images/')
likes = models.IntegerField()
dislikes = models.IntegerField()
How can I organize a good working system so all the products a user bought are saved inside the bought_products column and all the products a vendor sold can be saved inside the sold_products column. Do I have to use a ForeignKey for that or is there something more suitable for this situation? Also, if there is anything unwise about the existing structure of the database model (for example the current image field column only saves the link but not the image itself which is kinda weird...), please feel free to correct me :).
Many thanks in advance :D
In this case I suggest to make bought_products and sold_products instances of ManyToManyField because the same product can be bought by multiple Users and sold by multiple vendors
Firstly I would start by reading the following documentation on django auth customization. Seems like that would help you out a little bit.
https://docs.djangoproject.com/en/2.2/topics/auth/customizing/
Additionally, I think you need to better evaluate your data modelling to make each model more explicit/clearly defined. See example below:
class Products(models.Model):
vendor = models.ForeignKey(VendorData, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
description = models.CharField(max_length=1000)
price = models.IntegerField()
pub_date = models.DateTimeField('Date published')
image = models.ImageField(upload_to=b'shop/media/images/')
likes = models.IntegerField()
dislikes = models.IntegerField()
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=100)
active = models.BooleanField(default=True)
class ProductCategory(models.Model):
product = models.ForeignKey(Products, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_add_now=True)
From there I would construct a separate model which would store the customer purchased items. Since you already have a model which stores the vendor to product data, you shouldn't need anything additional to identify how many sales a particular vendor has.

How to join multiple models and get the result in pythonic way?

I have 4 models.
class User(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField()
class Subscription(models.Model):
user_id = models.ForeignKey(User)
title = models.CharField()
class Address(models.Model):
user_id = models.ForeignKey(User)
street = models.CharField()
class Wallet(models.Model):
user_id = models.ForeignKey(User)
balance = models.DecimalField(max_digits=6, decimal_places=2)
Here I want to get the subscription rows along with the respected user address and wallet balance. Is that possible to retrieve in a single query (ORM)?
I heard about select_related() and prefetch_related(). But not sure how to put all together in a single queryset.
How can I achieve this in pythonic way?
Have you tried to follow this snippet from documentation?
Having a User object instance you can do something like this to access subscriptions:
user.subscription_set.all()
It will require separate calls to different managers to collect all your data though.
First of all remove _id from FK fields. You'll still have subscription.user_id (int) and subscription.user which is User. Right now you have to write subscription.user_id_id for accessing id.
Do you understand that user can have multiple wallets and addresses with you db design?
It is not possible to do it in a single query with ORM. But it is possible to do it in 3 queries (doesn't matter how many records).
UPDATED:
class User(models.Model):
name = models.CharField()
class Subscription(models.Model):
user = models.ForeignKey(User, related_name='subscriptions')
title = models.CharField()
class Address(models.Model):
user = models.ForeignKey(User, related_name='addresses')
street = models.CharField()
class Wallet(models.Model):
user = models.ForeignKey(User, related_name='wallets')
balance = models.DecimalField(max_digits=6, decimal_places=2)
subscriptions = Subscription.objects.select_related('user').prefetch_related(
'user__wallets', 'user__addresses')
for s in subscriptions:
print(s.user.name)
for wallet in s.user.wallets.all():
print(wallet.balance)
for address in s.user.addresses.all():
print(address.street)

Django Models relations

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

Django Foreign key query

I have the following modle
class PatientContact(models.Model):
uid = models.CharField(max_length=10)
name = models.CharField(max_length=100)
phone = PhoneNumberField()
class Patient(models.Model):
name = models.CharField(max_length=100)
date_of_birth = models.DateField()
contact = models.ForeignKey(PatientContact)
class Appointment(models.Model):
patient = models.ForeignKey(Patient)
time = models.DateTimeField()
I can get the list of patients registered under a user:
Patient.objects.filter(contact=uid)
How could I get the list of appointment for a user from the above model?
Used case:
The list of appointments scheduled by user (uid=1234)
Not sure how to perform a backward relationship to get list of appointments for a given uid.
If I understood you correctly, this isn't backward, it's just two levels deep:
Appointment.objects.filter(patient__contact__uid=1234)

Categories