Django usage of ForeignKey - python

I have this micro ticket "system"
\\models.py
class Ticket(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
default=None,
null=True,
on_delete=models.CASCADE,
)
title = models.CharField(max_length=200)
description = models.TextField()
creator_adress = models.GenericIPAddressField(null=True)
start_date = models.DateTimeField(default=timezone.now)
ticket_waiting = models.BooleanField(default=True)
ticket_solved = models.BooleanField(default=False)
reopened_counter = models.IntegerField(default=0)
...
Until now, only one message (when the user opens the ticket) can be sent by the user, which will be forwarded to the admin. But the admin and the user can't write any other messages back and forth under the ticket yet.
If you use a new model for this, which is connected to every single ticket like so?
class TicketMessages(models.Model):
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
admin_message = models.TextField()
user_message = models.TextField()
What is the best way to implement this?
Thank you very much :>

you can achieve this efficiently with the following method,
create a model for ticket message :-
class TicketMessages(models.Model):
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
message = models.TextField() #this will be the message
message_by = # you can use a foreign key or a choices option to select between the admin or user
reply_to = models.ForeignKey("self") # if this is a reply to existing message
This is kind of an good and efficient solutions as per my understanding of your problem .... if you need something else or something more, let me know I'd love to help you.
Thanks !

Related

Django user subscribe user relation

I`m creating a simple blog now, and the main problem is to create a relation between Users. I use a default django User which should subscribe another user who is an author of post.
I have only one Post model in my app
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=128)
content = models.TextField(blank=True)
created_on = models.DateTimeField(auto_now_add=True)
seen = models.ManyToManyField(User, related_name='blog_posts', blank=True)
The relationship you're referring to isn't about the Post model as I understand it. So I think it might be better if you create a separate model. I share a model below as an idea, you can edit field names or add/delete fields according to your needs.
class AuthorSubscription(models.Model):
author = models.OneToOneField(User, on_delete=models.CASCADE, 'author_subscription')
subscribers = models.ManyToManyField(User, related_name='subscriptions', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

How to filter by BooleanField in Django?

I have been having a hard time accomplishing this task and it seems that I cannot get help anywhere I turn. I am trying to send Memos to specific user groups in Django. Each user in each group should receive the Memo and be able to change the BooleanField to True to signify that they have read it.
I then need to be able to access the amount of users which received and have marked the BoolenField as True so I can create a table in a template which says [3/31 Read] and such.
I would like to not use GenericForeignkeys if possible and I would like to keep it as one Model if possible but I know that may not work. Currently I was trying this:
class Memo(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_time = models.DateTimeField(default=timezone.now)
sender = models.ForeignKey(User, on_delete=models.CASCADE)
receiver = models.ManyToManyField(Group)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('memos-detail', kwargs={'pk': self.pk})
I was going to access each user (receiver) within the group which is selected on the MemoCreateForm then apply that user to this model:
class ReceivedMemo(models.Model):
memo = models.ForeignKey(
Memo, related_name='user_memos', on_delete=models.CASCADE)
receiver = models.ForeignKey(
User, related_name='memos', on_delete=models.CASCADE)
read = models.BooleanField(default=False)
Then I was going to try to filter the ReceivedMemos by memo to see if each receiver has read the memo or not. But this is starting to get complicated and I am not sure if it will work. Am I going about this the right way? Or should I be able to have one Model such as:
class Memo(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_time = models.DateTimeField(default=timezone.now)
sender = models.ForeignKey(User, on_delete=models.CASCADE)
receiver = models.ForeignKey(User, on_delete=models.CASCADE)
read = models.BooleanField(default=True)
Seems that each object would have the BooleanField applied to the object and not the user though.
The ReceivedMemo model seems more appropriate rather than the read bit, but the issue with this approach is that whenever you create a new Memo you need to also create lots of (for every User in the Group) ReceivedMemo objects with read=False? This seems pointless. Maybe you can just store the Users which actually read this thing, and for everyone that's left, consider he has not read it. I.e.
class Memo(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_time = models.DateTimeField(default=timezone.now)
sender = models.ForeignKey(User, on_delete=models.CASCADE)
receiver = models.ManyToManyField(Group)
read_by = models.ManyToManyField(User)

How to create two different users(doctor and patient) using Abstractuser class in Django so that both of them can perform their own role

I want to create two users with these details.
class Doctor(models.Model):
username = models.CharField(max_length=500)
password = models.CharField(max_length=500, null=True)
gender = models.CharField(choices=GENDER_CHOICES, max_length=128)
specialties = models.CharField(max_length=1000)
education = models.CharField(max_length=1000)
hospitals = models.CharField(max_length=1000)
rate = models.FloatField()
email = models.EmailField(unique=True)
description = models.TextField(null=True)
class Patient(models.Model):
username = models.CharField(max_length=500)
password = models.CharField(max_length=500, null=True)
email = models.EmailField(unique=True)
gender = models.CharField(choices=GENDER_CHOICES, max_length=128)
age = models.IntegerField()
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
I'm starting to use this approach either, and judging for the time your question have here, it is very probable that you already figured this out, but I want to answer this since I was looking for an answer not that long ago, and maybe this could help others.
Anyway, I was previously using the 'profile like' way before this AbstractUser one, but in your answer I see them both mixed, in your patient model you're using a OneToOne FK to the original auth_user model, but you're asking for the AbstractUser.
So just in case you're looking for the 'Profile like' which is really called 'proxy model' option, you're already almost done, you would just need to add a OneToOne field to the User as in your Patient model but in the Doctor model, and then you would have two models with extra information, but nothing to do with login, access or permissions, just for profile, ready to go.
The docs on the following link explain this
Proxy model basic documentation
Now if what you're looking for is to use the other way, substituting the user model, for which you need the AbstractUser, what you need to do (or better stated, what you could do, which is what I'm doing now) is to create a base custom user class.
Which you can see a full example in the documentation
In your case
class MyBaseUser(AbstractUser):
username = models.CharField(max_length=500)
password = models.CharField(max_length=500, null=True)
email = models.EmailField(unique=True)
gender = models.CharField(choices=GENDER_CHOICES, max_length=128)
class Doctor(MyBaseUser):
specialties = models.CharField(max_length=1000)
education = models.CharField(max_length=1000)
hospitals = models.CharField(max_length=1000)
rate = models.FloatField()
description = models.TextField(null=True)
class Patient(MyBaseUser):
age = models.IntegerField()
Now, remember that you need to specify in the settings the AUTH_USER_MODEL, you could follow a cookiecutter template so all of this would be pre-formatted.
Also, you can add your USERNAME_FIELD within your MyBaseUser class to state which field would be used as login username, as well as the REQUIRED_FIELDS in the same class.
Have a nice one, as our friend Destin likes to say.

Django ORM relations one-to-many

I have a model:
class Product(models.Model):
title = models.CharField(max_length=200)
url = models.URLField()
pub_date = models.DateTimeField()
votes_total = models.IntegerField(default=1)
image = models.ImageField(upload_to='images/')
icon = models.ImageField(upload_to='images/')
body = models.TextField()
hunter = models.ForeignKey(User, on_delete=models.CASCADE)
Now I'd like to add a functionality of upvoters to know on what products user has already voted. I need this to allow users vote on the one product only once.
Again, to clarify - user can vote on several products but only once on each.
So the relation is one product - many users (upvoters).
I tried to add the next field but cannot make a migration even if default field is provided. Also I tried to clear the database but again cannot make it work.
upvoters = models.ForeignKey(User, on_delete=models.CASCADE, related_name='upvoted')
I suppose it works the next way:
Field to determine upvoted products.
To check if user has been upvoted on product, call: User.upvoted.filter(id=product.id).count() == 1
This means that user has already upvoted on this product.
What's wrong? What should I change to make it work?
You will have to use ManyToMany, but you can use a custom through model to restrict the product/vote combinations.
To Product class, add:
voters = models.ManyToManyField(User, through='ProductVote', related_name='product_voters')
Then add the custom through model:
class ProductVote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Vote, on_delete=models.CASCADE)
class Meta:
unique_together = ['user', 'product']
If you try to add a vote for the same user/product combination, an IntegrityError will be raised.

Django getting especific object using QuerySet in reverse relationship many-to-one

Lets say I have the following models:
Chat(models.Model):
community = models.ForeignKey(Community, related_name="chats", null=True, blank=True)
....
Community(models.Model):
slug = models.CharField(max_length=250, unique=True, default='')
....
Profile(models.Model):
public_name = models.CharField(max_length=20, unique=True)
community_subscriptions = models.ManyToManyField('Community', through='CommunitySubscription')
chat_subscriptions = models.ManyToManyField('Chat', through='ChatSubscription')
....
ChatSubscription(models.Model):
profile = models.ForeignKey(Profile, unique=False, related_name='chat_subscription')
chat = models.ForeignKey(Chat, null=True, blank=True, related_name='chat_subscribers')
....
CommunitySubscription(models.Model):
....
In a view I want to do the following:
profileA = Profile.objects.get(public_name=public_nameA)
profileB = Profile.objects.get(public_name=public_nameB)
community = Community.objects.get(slug=community_slug)
try:
# I want to get the unique chat that involves both profiles for a specific community or get DoesNotExist (or None) if there is not such chat.
chat = Chat.objects.????????????
except Chat.DoesNotExist:
....
If the chat exist then both profiles will have a ChatSubscription object relating the profile with the chat.
Is it possible to do this kind of filtering using Django QuerySets in one single line? If not what would be the most efficient way to do it in more than one line?
Thanks a lot in advance.
Pretty complex, so try using the Q object to do a 'AND' query (assuming I got what you're trying to do):
from django.db.models import Q
Chat.objects.filter(Q(chatsubscription__profile__in=[profileA,profileB]) & Q(community=communty))

Categories

Resources