Changed the relationship of a Foreign Key | Django model - django

my buyer field from the Sell model had relationship with the Buyer model like this:
class Buyer(models.Model):
name = models.CharField(max_length=200, blank=True)
description = models.CharField(max_length=200, blank=True)
class Sell(models.Model):
item = models.OneToOneField(Buy, related_name='sell', on_delete=models.CASCADE)
buyer = models.ForeignKey(**Buyer**, related_name='sell', on_delete=models.CASCADE)
But now, it's set to 'User' model as you can see below:
class Sell(models.Model):
item = models.OneToOneField(Buy, related_name='sell', on_delete=models.CASCADE)
buyer = models.ForeignKey(**User**, related_name='sell', on_delete=models.CASCADE)
When I go to Django admin, it shows me all the available users from the User model but if I try to save, I got an error like this:
insert or update on table "dma_sell" violates foreign key constraint "dma_sell_buyer_id_4d165f92_fk_dma_buyer_id"
DETAIL: Key (buyer_id)=(13) is not present in table "dma_buyer".
I'm wondering I should NOT have changed this but what is the best way to correct that? I really need to relate the buyer field with User model!
Thank you!

After searching for a long time, I discovered 2 great websites!
Links:
https://simpleisbetterthancomplex.com/tutorial/2016/07/26/how-to-reset-migrations.html
https://aistlabs.com/switch-foreignkey-one-model-another-and-keep-old-data-migration-pain/
Just recording here for those who can ask in the future!

Related

How to store multiple userids in same model?

I'm fairly new to Django and attempting to store a model which will hold transaction information for a purchase between 2 users; a buyer and seller. I therefore want to store 2 UserIDs:
class Transaction(models.Model):
transactionid = models.AutoField(primary_key=True)
# USERID OF SELLER
# USER ID OF BUYER
orderid = models.ForeignKey('Order', db_column='orderid', on_delete=models.SET_NULL, blank=True, null=True)
status = models.CharField(choices=PAYMENT_STATUS, default='pending', max_length=50)
timestamp = models.DateTimeField(auto_now_add=True)
I want to use the following foreign key:
seller = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
however, to my understanding, this will only store the current logged in user which means I wouldn't be able to set both? Is there a better way to do this rather than modifying the model twice (esentially from both accounts)?
Any reccomendations or advice appreciated, thank you!
I hope, in the Transaction model you are going to add the entry if someone made any purchase. Buyer Id you can get from the current user. Seller ID yo can get from the product information.
For adding more than 1 foreign key with the same Model, you can use the related_name parameter.
class Transaction(models.Model):
transactionid = models.AutoField(primary_key=True)
seller = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='seller_name')
buyer = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='buyer_name')

How to change the primary key of manytomany table in django

I am changing the primary key of the legacy database. I was able to change the primary key by setting id as the primary key.
Before
class User(models.Model):
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
After
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
Then
python manage.py makemigrations
python manage.py migrate
This is working fine.
But I also want to change the default primary key of the tables created via ManyToMany feild.
User Model
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
UserProfile Model
class UserProfile(models.Model):
id = models.BigIntegerField(primary_key=True)
address = models.CharField(max_length=5)
father_name = models.CharField(max_length=5)
pincode = models.CharField(max_length=5)
user = models.ManyToManyField(User)
The ManytoMany field creates table called User_user_userprofile with id as Autofield basically previous or default django primary key.
id, user_id, userprofile_id
ManytoMany Table
Now, How to change the primarykey of ManytoMany Feild ie id created by Django?
PS:
Django: 1.11
Python: 2.7.5
DB: Sqlite3 3.7.17 2013-05-20
I stumbled upon this problem today, and ended up solving it by using the through argument of the ManyToManyField. I solved it for Django v3.2.6 however, but the documentation for v1.11 mentions the same behavior for the same argument, so hopefully the solution should work for your version of Django too. Here's the link to the documentation for v1.11 ManyToManyField.through
What the through argument allows you to do is to create the intermediary table (created automatically by ManyToManyField) yourself. You get finer control of how the intermediary table should look like, what fields it should have and what their behavior should be. Hope you are getting a picture.
Let me give you the example of the problem I faced and how I solved it. Hopefully that will make this clearer.
I was trying to establish a many-to-many relationship between two of my existing models.
My first model looks like this,
class BanglaWords(models.Model):
class Meta:
verbose_name_plural = 'Bangla Words'
bng_id = models.CharField(max_length=16, primary_key=True)
bangla_word = models.CharField(max_length=64)
def __str__(self):
return self.bangla_word
and the second one looks like,
class EnglishWords(models.Model):
class Meta:
verbose_name_plural = 'English Words'
eng_id = models.IntegerField(primary_key=True)
word = models.CharField(max_length=64)
bangla_word = models.ManyToManyField(BanglaWords)
def __str__(self):
return self.word
But this resulted in an intermediary table wordnet_englishwords_bangla_word which looked like this,
wordnet_englishwords_bangla_word
id
englishwords_id
banglawords_id
But I didn't want this, I wanted bng_id to be the pk for this table. I solved the problem with ManyToManyField.through as follows,
I defined the intermediary model(table) myself and with the through argument, I pointed to the new intermediary model I created and instructed django to create the table the way I wanted it.
First I created the intermediary model,
class BanglaEnglishRelations(models.Model):
class Meta:
verbose_name_plural = 'Bangla English Relations'
bng_id = models.OneToOneField('BanglaWords', primary_key=True, on_delete=models.CASCADE)
eng_id = models.ForeignKey('EnglishWords', on_delete=models.CASCADE)
which defines bng_id as the primary key as I desired.
Second, I told the ManyToManyField in EnglishWords to base the table on BanglaEnglishRelations like,
bangla_word = models.ManyToManyField(BanglaWords, through=BanglaEnglishRelations)
This resulted in the table wordnet_banglaenglishrelations which looked like,
wordnet_banglaenglishrelations
bng_id_id
eng_id_id
and surved my purposes. You can do something similar to solve your problem and promote whatever field to a pk.

Template tag for going from model1 to model2 that has foreign key to model1

Is there a template tag or a way that I can go from my main model to a specific model that has a foreign key to my main model?
models.py
class BillingAddress(models.Model):
user = models.ForeignKey(UserCart, on_delete=models.CASCADE)
address1 = models.CharField(max_length=120, null=True)
class HomeAddress(models.Model):
user = models.ForeignKey(UserCart, on_delete=models.CASCADE)
address1 = models.CharField(max_length=120, null=True)
class UserCart(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
I want to get the 'address1' field from the BillingAddress that is related to a usercart. I don't think that I can use {{usercart.address1}} as both HomeAddress and BillingAddress have a field called address1 and are related to the usercart.
Thanks!
Dont worry, you can get it normally. Because BillingAddress and HomeAddress FK to UserCart.This mean from UserCart, you have 2 set different is usercart.billingaddress_set and usercart.homeaddress_set. This is 2 list of BillingAddress and HomeAddress related with UserCart.
If you want get one address1 field. You must know what set you want get it. Like example : usercart.billingaddress_set.first().address1 will give you first record which BillingAddress related with UserCart.
If you still worry, you can change name of billingaddress_set or homeaddress_set by related_name to anything name you want. Read related_name for more information

Get all related field in Django model

I am struggling to understand how one-to-many and many-to-many relation works in Django model. My schema looks something like this so far, I am open for suggestions to make it better.
A many-to-many relation between users and team. Also, there will be schedules that belong to a particular user of a team.
This is how my model looks like so far,
class Team(models.Model):
tid = models.AutoField(primary_key=True)
team_name = models.CharField(max_length=30)
manager_name = models.CharField(max_length=30)
class Schedule(models.Model):
sid = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
pay_rate = models.CharField(max_length=30)
location = models.CharField(max_length=50)
class BelongsTo(models.Model):
bid = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE)
Question: I want to get the information of each user, what are their schedules and which team each schedule belongs to. How would I to do it? I have tried BelongsTo.objects.select_related().all(), but it is not working for me.
Note: I am open for suggestions, if something is wrong with my schema or model or the approach, please let me know.
BelongsTo is seems like utility table.So
BelongsTo.objects.all().values('user', 'team__team_name', 'schedule')
Your schema looks almost right, but I would modify it a little bit. In particular, I will change how Schedule is implemented. Instead of having a sid in the User Belongs To join-table, I would include the user and team in the Schedule table as foreign keys.
This is how the Django models should then look like:
class User(models.Model):
username = models.CharField(max_length = 200)
# put other fields like password etc. here
class Team(models.Model):
team_name = models.CharField(max_length=30)
manager_name = models.CharField(max_length=30)
user = models.ManyToManyField("User")
class Schedule(models.Model):
user = models.ForeignKey("User")
team = models.ForeignKey("Team")
date = models.DateField()
start_time = models.TimeField()
end_time = models.TimeField()
pay_rate = models.CharField(max_length=30)
location = models.CharField(max_length=50)
Note the following:
You don't need to have a primary key field in the models because Django adds a primary key field called pk or id automatically.
Note the absence of the User Belongs To model. Django implements join-tables like User Belongs To automatically when you use a ManyToManyField. See the Django docs on many-to-many relationships.
You also don't need on_delete = models.CASCADE on ForeignKey fields, because this is the default behavior.
To see how to get information about users, teams and schedule from this configuration of models, consult the Django documentation on making db queries. It's quite easy.

Ordering a Foreign Key Field by Date Added

I have the following two models:
class Position(models.Model):
position = models.CharField(max_length=100)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
positions = models.ManyToManyField(Position, blank=True, null=True)
This creates a database table called userprofile_userprofile_positions, with the following three columns:
id
userprofile_id
position_id
How would I add a fourth field to this table --
created_at = models.DateTimeField(auto_now_add=True)
I would like to do this through django, if possible. Thank you.
Create a new model and specify it in the through attribute of your ManyToMany. The Django docs have a section on this exact use case: Extra fields on many-to-many relationships.