I'm trying to create a foreignkey relationship in DRF models with an on_delete
fk_city = models.ForeignKey("region_mgmt.City", "warehouses", on_delete=models.SET_NULL)
TypeError: __init__() got multiple values for argument 'on_delete'
below is my code:
from django_extensions.db.models import TimeStampedModel
class State(TimeStampedModel, models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=100)
postal_code = models.CharField(max_length=20, blank=True, null=True)
fk_country = models.ForeignKey(Country, related_name="states", on_delete=models.CASCADE)
def __str__(self):
return self.name
class City(TimeStampedModel, models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=100)
postal_code = models.CharField(max_length=20, blank=True, null=True)
fk_state = models.ForeignKey(State, related_name="cities", on_delete=models.CASCADE)
def __str__(self):
return self.name
and in another module I have the following model
class Warehouse(TimeStampedModel, models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=255, null=False, blank=False)
address = models.TextField(null=False, blank=False)
fk_city = models.ForeignKey("region_mgmt.City", "warehouses", on_delete=models.SET_NULL)
contact_no = models.CharField(max_length=100)
does anyone know the reason and its solution?
The second parameter of a ForeignKey is the on_delete=… parameter [Django-doc], so you specify two values for this. Likely you want to use your warehouses as related_name=… parameter [Django-doc], so you implement this as:
class Warehouse(TimeStampedModel, models.Model):
# …
fk_city = models.ForeignKey(
'region_mgmt.City',
related_name='warehouses',
on_delete=models.SET_NULL,
null=True
)
Related
Just a fool question I have a model Exam which contains a field Subject which I want to connect with 3 or 4 or even 5 subjects like foreign key connect one with it.
# 1 type
class Math(models.Model):
id = models.CharField(primary_key=True, max_length=200, blank=True)
chapter = models.ForeignKey(Chapters, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
marks_contain = models.IntegerField(default=10)
question = RichTextUploadingField()
hint = RichTextUploadingField()
created_at = models.DateTimeField(auto_now_add=True, blank=True)
# 2 type
class Science(models.Model):
id = models.CharField(primary_key=True, max_length=200, blank=True)
chapter = models.ForeignKey(Chapters, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
marks_contain = models.IntegerField(default=10)
question = RichTextUploadingField()
hint = RichTextUploadingField()
created_at = models.DateTimeField(auto_now_add=True, blank=True)
# 3 type
class Computer(models.Model):
id = models.CharField(primary_key=True, max_length=200, blank=True)
chapter = models.ForeignKey(Chapters, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
marks_contain = models.IntegerField(default=10)
question = RichTextUploadingField()
hint = RichTextUploadingField()
created_at = models.DateTimeField(auto_now_add=True, blank=True)
class Exam(models.Model):
id = models.AutoField(primary_key=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
name = models.CharField(max_length=255)
subject = models.ForeignKey([object.Math or object.Science or object.Computer]) # I want to do something like this
I know this is not possible with foreign-key but what is the way to do things like this?
It's possible with ManyToMany, but you have to create new model:
from django.utils.module_loading import import_string
class Subject(models.Model):
class_name = models.CharField(...)
def get_class(self):
return import_string(f"app_name.models.{self.class_name}")
class Exam(...):
...
subject = models.ManyToManyField(Subject, default=None, blank=True)
Then simply create Subject object for each model you want to be with class_name exactly as you have your subject __class__ name, i.e. Subject.objects.create(class_name="Math"). Then replace app_name with name of your app that models.py is inside.
If you need real class from Subject class just call subject.get_class(), and you will get object: <class 'app_name.models.Math'>.
I have a user model that has to go through several tasks such as completing their information, taking some tests, and interviews. So I added a progress level field that shows the user status at the moment. this is my model:
class User(AbstractUser):
id = models.AutoField(primary_key=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
isPreRegistered = models.BooleanField(default=False)
role = models.CharField(max_length=25, null=True, choices=USER_ROLE_CHOICES, default=USER_ROLE_CHOICES[0][0])
role_id = models.CharField(max_length=10, default='applicant')
username = models.CharField(unique=True, max_length=13)
first_name = models.CharField(max_length=32, null=True, default=None)
last_name = models.CharField(max_length=64, null=True, default=None)
gender = models.CharField(max_length=10, null=True)
personalInfo = models.OneToOneField(PersonalInfo, on_delete=models.CASCADE, null=True)
contactInfo = models.OneToOneField(ContactInfo, on_delete=models.Case, null=True)
eliteInfo = models.OneToOneField(EliteInfo, on_delete=models.CASCADE, null=True)
progress_level = models.CharField(max_length=25, null=True, choices=USER_PROGRESS_LEVELS, default=USER_PROGRESS_LEVELS[0][0])
and there are multiple models which are connected to the user model using a foreign key relation.
this is one of the models I added here for instance:
class PsychologicInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
final_assessment = models.TextField(null=True, blank=True)
is_approved = models.CharField(max_length=64, blank=True)
is_interviewed = models.BooleanField(default=False)
I want to write a signal or a save method that does something like this:
if the is_interviewed field was True, change that progress_level to USER_ROLE_CHOICES[1][0]
I have no idea how to do this so thanks for the tips
You can override the .save() method of PsychologicInfo
class PsychologicInfo:
...
def save(self):
super().save()
if self.is_interviewed:
self.user.role = USER_ROLE_CHOICES[1][0] # or enter value here
self.user.save()
or you can use Django signals.
I want to add one subquery to my query. And I created a #property in Transaction. Found on the Internet that this is what I need. But I do not fully understand how they work. How to use it?
views.py(Query)
paymentsss = Transaction.objects.all().select_related('currency',
'payment_source__payment_type',
'deal__service__contractor',).
models.py
class PayerPaymentSource(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
payer_id = models.BigIntegerField(blank=True, null=True)
payment_type = models.ForeignKey(PaymentType, max_length=64, blank=True, null=True, on_delete=models.CASCADE)
source_details = models.TextField(blank=True, null=True) # This field type is a guess.
class Meta:
managed = False
db_table = '"processing"."payer_payment_source"'
class Transaction(models.Model):
id = models.BigIntegerField(blank=True, null=False, primary_key=True)
currency = models.ForeignKey(Currency, null=True, on_delete=models.CASCADE)
deal = models.ForeignKey(Deal, null=True, on_delete=models.CASCADE)
# service_instance = models.ForeignKey(ServiceInstance, null=True, on_delete=models.CASCADE)
payment_source = models.ForeignKey(PayerPaymentSource, null=True, on_delete=models.CASCADE)
payment_date = models.DateTimeField(blank=True, null=True)
amount = models.IntegerField(blank=True, null=True)
status = models.CharField(max_length=255, blank=True, null=True)
context = models.TextField(blank=True, null=True)
#property
def bank_card_details(self):
return PayerPaymentSource.objects.filter(self.payment_source.source_details,
payment_type='bank_card_details')
class Meta:
managed = False
db_table = '"processing"."transaction"'
UPD: print(payment.bank_card_details) works, but it creates a lot of similar queries. How to fix it?
The #property decorator is just a convenient way to call the property() function, which is built in to Python. This function returns a special descriptor object which allows direct access to the method's computed value.
For example in your view
obj = Transaction.objects.get(pk=pk)
#now you can get the bank_card_details like this:
print(obj.bank_card_details)
My model has a default pk with AutoField (integer) but later on i discovered that i need to use BigAutoField instead!
And also i have data in then with other models referencing the student model:: how do i change the pk field to BigAutoField and also reflects on other referencing models
class Student(models.Model):
matric_no = models.CharField(max_length=20, unique=True) # first set it to U(random)
password = models.CharField(max_length=128)
session = models.ForeignKey(Session, null=True)
programme = models.ForeignKey(Programme, null=True)
school = models.ForeignKey(School, null=True)
course_comb = models.ForeignKey(CourseComb, null=True)
serial = models.IntegerField(null=True)
current_level = models.CharField(max_length=3, choices=LEVEL_CHOICES, default='100', null=True)
last_login = models.DateField(null=True)
is_active = models.CharField(max_length=1, default=1, choices=((1, 1), (0, 0)))
created_at = models.DateTimeField(default=timezone.now)
updated_at = models.DateTimeField(auto_now=True)
a model referencing Student
class Profile(models.Model):
student = models.OneToOneField(Student, on_delete=models.CASCADE)
attachment = models.ImageField(null=True, blank=True, verbose_name="Profile Image")
surname = models.CharField(max_length=255, null=True, verbose_name="Surname")
othernames = models.CharField(max_length=255, null=True, verbose_name="Othernames")
SEX_CHOICES = (
("M", "Male"),
("F", "Female")
)
Set primary_key=True in the field definition:
id = models.BigAutoField(primary_key=True)
If you want to use this in multiple models you could also make an abstract model and let others inherit it:
class BigPkAbstract(models.Model):
id = models.BigAutoField(primary_key=True)
class Meta:
abstract = True
And in your other models:
class SomeModel(BigPkAbstract):
<your model here>
I have the following models.
class Category(MPTTModel):
name = models.CharField(max_length=100, null=False, blank=False)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=250, null=False, blank=False)
category = models.ForeignKey('Category')
price = models.DecimalField(decimal_places=2, max_digits=7)
def __unicode__(self):
return self.name
class ProductAttribute(models.Model):
products = models.ManyToManyField('Product')
category = models.ForeignKey('Category')
property = models.CharField(max_length=250, null=False, blank=False)
value = models.CharField(max_length=250, null=False, blank=False)
I need to be able to select products based on a given category, and a given attribute.
For example, if I have the product "Blender", I want to select all blenders within a given category, with a given attribute (such as brand = black & decker).