So, I have a Comment model in a django project I am trying to make, what I want to do is to override the on_delete function of the ForeignKey
COMMENT_TYPES = (
(1, "Comment"),
(2, "Reply to a comment"))
class Comment(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
comment_text = models.CharField(max_length=80, blank=False, null=False)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True,editable=False)
date_created = models.DateTimeField(auto_now_add=True)
date_edited = models.DateTimeField(auto_now=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent_comment = models.ForeignKey('self', blank=True, null=True, on_delete=models.SET_NULL)
comment_type = models.IntegerField(choices=COMMENT_TYPES, default=1)
What I want is that when I delete a comment, then all the comments that were linked to the deleted comment, their comment_type should change from 2('reply to a comment') to 1('comment'), so is there a way to override the on_delete function, SET_NULL so that I can change the value in the comment_type field?
Related
I want to pass gamingpc and pcComponent on OrderItem item field so I can add one of them in item field
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
item = models.ForeignKey(
gamingpc, on_delete=models.CASCADE, blank=True, null=True)
product = models.ForeignKey(
PcComponent, on_delete=models.CASCADE, blank=True, null=True)
you must use content-type for this situation .
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
content_object = GenericForeignKey()
object_id = models.CharField(max_length=100, null=True, blank=True)
content_type = models.ForeignKey(
ContentType, on_delete=models.CASCADE, null=True, blank=True,
limit_choices_to=(models.Q(model__in=['PcComponent', 'gamingpc']))
here is my models.py code. im trying to run the python3.8 manage.py migrate command to create the tables for the database but i keep getting this error, what could be the issue here. Profile is a class in the models.py code. if you need another part of my code please ask
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Image(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null='True', blank=True)
image = models.ImageField(upload_to = 'pics/')
name = models.CharField(max_length=50,blank=True)
caption = models.CharField(max_length=250, blank=True)
likes = models.ManyToManyField(User, related_name='likes', blank=True, )
date_posted = models.DateTimeField(default=timezone.now)
class Comment(models.Model):
comment = models.TextField()
image = models.ForeignKey('Image', on_delete=models.CASCADE,related_name='comments',null='True', blank=True )
name = models.CharField(max_length=100, blank=True)
user = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='comments',null='True', blank=True )
created = models.DateTimeField(auto_now_add=True, null=True)
class Profile(models.Model):
name = models.OneToOneField(User, on_delete=models.CASCADE)
profile_picture = models.ImageField(upload_to='images/', default='default.png')
bio = models.TextField(max_length=500, default="My Bio", blank=True)
followers = models.ManyToManyField(User, related_name="followers", blank=True)
following = models.ManyToManyField(User, related_name="following", blank=True)
You are using the Profile class before defining it. Switch the order of the Comment class and Profile class. Like so:
class Profile(models.Model):
name = models.OneToOneField(User, on_delete=models.CASCADE)
profile_picture = models.ImageField(upload_to='images/', default='default.png')
bio = models.TextField(max_length=500, default="My Bio", blank=True)
followers = models.ManyToManyField(User, related_name="followers", blank=True)
following = models.ManyToManyField(User, related_name="following", blank=True)
class Comment(models.Model):
comment = models.TextField()
image = models.ForeignKey('Image', on_delete=models.CASCADE,related_name='comments',null='True', blank=True )
name = models.CharField(max_length=100, blank=True)
user = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='comments',null='True', blank=True )
created = models.DateTimeField(auto_now_add=True, null=True)
You are referencing the Profile class before this is constructed. You can make use of a string literal instead:
class Comment(models.Model):
# …
user = models.ForeignKey(
'Profile', # ← a string literal
on_delete=models.CASCADE,
related_name='comments',
null='True',
blank=True
)
# …
It might also be better to rename the field to profile, to make it clear the ForeignKey is referencing a Profile object, not a User object:
class Comment(models.Model):
# …
profile = models.ForeignKey( # ← rename to profile
'Profile',
on_delete=models.CASCADE,
related_name='comments',
null='True',
blank=True
)
# …
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
This is my models. What is the best approach?
OneToOneField allows to create only one comments for all time.
class Person(models.Model):
first_name = models.CharField(
max_length=512,
blank=True,
null=True,
)
last_name = models.CharField(
max_length=512,
blank=True,
null=True,
)
class Product(models.Model):
slug = SlugField()
name = NameField()
description = DescriptionField()
class Comment(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
person = models.OneToOneField(Person, on_delete=models.CASCADE)
text = models.TextField(null=True, blank=True)
# You can use 'unique_together' feature of model
class Product(models.Model):
slug = SlugField()
name = NameField()
description = DescriptionField()
class Comment(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
text = models.TextField(null=True, blank=True)
class Meta:
unique_together = ("person", "product")
What you want is multiple comments per User, and multiple comments per Product. However, you need to ensure uniqueness for users and products inside comments. This can be achieved using unique_together (see https://docs.djangoproject.com/en/2.2/ref/models/options/#unique-together):
class Comment(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
text = models.TextField(null=True, blank=True)
class Meta:
unique_together = ['person', 'product']
I believe you need to add Product to Comment as well:
class Comment(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
text = models.TextField(null=True, blank=True)
class Meta:
unique_together = ['person', 'product']
So basically i have to make sure Users that are from the same department field to view and create any datas in the database. Not sure how to apply it using field-based user permissions?
class Profile(AbstractUser):
class Meta:
verbose_name_plural = 'Profiles'
company = models.CharField(max_length=30, null=True)
contact = models.CharField(max_length=20, null=True)
branch = models.ForeignKey('generals.Branch',
on_delete=models.CASCADE)
department = models.ForeignKey('generals.Department',
on_delete=models.CASCADE)
created_by = models.CharField(max_length=20)
modify_by = models.CharField(max_length=20)
modify_date = models.DateTimeField(default=datetime.now, blank=True)
is_active = models.BooleanField(default=False, null=True,
blank=True)
is_superuser = models.BooleanField(default=False, null=True,
blank=True)
is_staff = models.BooleanField(default=False, null=True,
blank=True)
def __str__(self):
return self.username
You should use what's already implemented in Django, and you'll gain a lot of time.
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.ForeignKey(Group, on_delete=models.CASCADE)
contact = models.ForeignKey('Person', on_delete=models.CASCADE)
branch = models.ForeignKey('generals.Branch',
on_delete=models.CASCADE)
department = models.ForeignKey('generals.Department',
on_delete=models.CASCADE)
created_by = models.ForeignKey('Person', on_delete=models.CASCADE)
modify_by = models.ForeignKey('Person', on_delete=models.CASCADE)
modify_date = models.DateTimeField(default=datetime.now, blank=True)
even though my eyes are burning because my syntax here is not PEP8 compliant, you should get the big picture: all the permissions are already handled by User and Group.
Just create a Group that has the name of the company, and give this group access (or not) to specific tables.
I have some models and fk on them to others.
models.py
class ElementMessages(models.Model)
element = models.ForeignKey(Element, on_delete=models.CASCADE)
sender = models.ForeignKey(UserAccount, on_delete=models.SET_NULL, null=True)
text = models.TextField(max_length=512, null=True)
send_time = models.DateTimeField(auto_now_add=True)
type = models.CharField(max_length=16, choices=MESSAGE_TYPES, default=SIMPLE)
type_dialog = models.CharField(max_length=10, choices=DIALOG_TYPE, default=DIALOG_TALK)
request = models.ForeignKey(ChatRequest, null=True, default=None, on_delete=models.CASCADE)
post_work = models.ForeignKey(PostWork, null=True, default=None, on_delete=models.CASCADE)
files = models.BooleanField(default=False)
class Element(models.Model):
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True)
artist = models.ForeignKey(Artist, on_delete=models.CASCADE, related_name='chat_element', null=True, blank=True)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='chat_element', null=True, blank=True)
element = models.ForeignKey('projects.Element', null=False, on_delete=models.CASCADE, related_name='chat_element')
When I try to delete Element object, it raises this:
django.db.utils.IntegrityError: insert or update on table "chat_elementmessages" violates foreign key constraint "chat_elementmessages_element_id_672e2ba2_fk_chat_element_id"
DETAIL: Key (element_id)=(87cdd8d7-47f0-4264-8aa7-ae21a8246fd8) is not present in table "chat_element".
But when I look at table in db, this key exists.
How to fix that?
As it turned out, problems were at Django pre_delete andpost_delete signals. They tried to refer to a non-existing object, that I'm try to delete. Fixed with simple check on the existence of the object.