Python Django M2M attribute via an intermediary model - django

I have a model with 2 M2M attributes: Connection is recursive and the ConnectionRequest uses an intermediary class. With Connection attribute, I am able to retrieve the connections of a user without problems (since I am using a native M2M field). But with ConnectionRequest is where I have challenges.
I would like to retrieve the 'connection requests' for this user but struggling with this natively. I have implemented it however programmatically (through a query) - but its not clean.
Basically, I would like to return the list of all connection requests. ie where the recipientAccount is the same as the parent class (Account) object.
class Account(models.Model):
firstName = models.CharField(
'First Name', max_length=100, blank=True, null=True)
lastName = models.CharField(
'Last Name', max_length=100, blank=True, null=True)
emailAddress = models.EmailField(
'Email Address', max_length=255, blank=True, null=True, unique=True)
connections = models.ManyToManyField('self', blank=True)
connection_requests = models.ManyToManyField(
'ConnectionRequest', blank=True, related_name='accounts')
def __str__(self):
return self.firstName + ' ' + self.lastName
class ConnectionRequest(models.Model):
senderAccount = models.ForeignKey(
Account, related_name='sender_Account', on_delete=models.CASCADE)
recipientAccount = models.ForeignKey(
Account, related_name='recipient_Account', on_delete=models.CASCADE)
def __str__(self):
return str(self.senderAccount.id) + ' to ' + str(self.recipientAccount.id)
I have an idea to try the below but suddenly realised that I am unable to access the Account object from the ConnectionRequest class (since its a parent object/class).
class ConnectionRequest(models.Model):
def __str__(self):
return self.__class__.objects.filter(
Q(recipientAccount=recipientaccount))
Should I be looking to implement this in the Account model? Perhaps as a method?
Thanks!

Related

A better way to orgainize django-channels one to one private chat models?

I want to model the database table of a django channels private chat in the most effective way possible so that retrieving the messages would not take a lot of time.
For that I have create a one to one room since every two users should have their unique room.
And I created a separate message table with a foreign key relation with the (oneToOneRoom) table.But what bothers me is that since the sender and the receiver of the message can only be one of the two users of the room I do not want set (sender and receiver) as foreign Key to the users table. Can I have a better implementation of that. Or is their any other way of modeling those tables. Any help would be highly appreciated.
Here is the models.py file.
class singleOneToOneRoom(models.Model):
first_user = models.ForeignKey(
User, on_delete=models.SET_NULL, related_name="first_user", blank=True, null=True)
second_user = models.ForeignKey(
User, on_delete=models.SET_NULL, related_name="second_user", blank=True, null=True)
room_name = models.CharField(max_length=200, blank=True, unique=True)
def __str__(self):
return f"{self.first_user}-{self.second_user}-room"
class Meta:
unique_together = ["first_user", "second_user"]
class messages(models.Model):
room = models.ForeignKey(
singleOneToOneRoom, on_delete=models.CASCADE, related_name="messages")
message_body = models.TextField()
sender = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_sender")
receiver = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_receiver")
date_sent = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.sender}_to_{self.receiver}"
The design seems ok. You can add more constraints to be sure, that message belongs to the right users.
Here my suggestions:
Make first_user and second_user NOT NULL fields.
Make sure, that you have exactly 1 room for users pair (first_user.id < second_user.id)
Make sure, that (receiver, sender) pair equals (first_user, second_user) pair
class singleOneToOneRoom(models.Model):
first_user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="first_user", null=False)
second_user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="second_user", null=False)
class Meta:
unique_together = ["first_user", "second_user"]
constraints = [
models.CheckConstraint(check=Q(first_user__id__lt=F('second_user__id')), name='unique_user_pair'),
]
class messages(models.Model):
room = models.ForeignKey(
singleOneToOneRoom, on_delete=models.CASCADE, related_name="messages")
message_body = models.TextField()
sender = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_sender")
receiver = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="msg_receiver")
class Meta:
constraints = [
models.CheckConstraint(
check=Q(sender=F('singleonetooneroom__first_user') & Q(receiver=F('singleonetooneroom__second_user'))
| Q(sender=F('singleonetooneroom__second_user') & Q(receiver=F('singleonetooneroom__first_user')),
name='valid_sender_and_receiver'
),
]

Django imeplement custom model field without migration

I'm trying to implement custom field in my model following the docs, My model is as follow:
class User(AbstractUser):
uid = models.CharField(
"uid", max_length=255, null=True, blank=True)
phone_number = models.CharField(
"Phone number", max_length=255, null=True, blank=True)
nickname = models.CharField(
"Nickname", max_length=255, null=True, blank=True)
eth_address = models.CharField("Eth address", max_length=255, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
# deleted
class eth_address_decrypted(models.Field):
description = 'eth_address_decrypted'
def __init__(self, *args, **kwargs):
return decrypt_string(self.eth_address)
class Meta:
db_table = "users"
pass
I have a eth_address field that it's value are encrypted, i need to display the decrypted value on the frontend, so i wrote custom field model as the docs and call it on my front end through query:
User.objects.get(eth_address_decrypted=value)
But it returning the following error:
Cannot resolve keyword 'eth_address_decrypted' into field. Choices are: created, date_joined, email, eth_address,
What am i doing wrong ?
Is there a way i can call user.eth_address_decrypted on object as a custom field or function without migrating it ? (because eth_address_decrypted just a convert from existed eth_adress)

Django 1.11: Can't get ManyToManyField to work

I have the following models:
class Address(models.Model):
address1 = models.CharField(max_length=150, null=True)
address2 = models.CharField(max_length=150, null=True, blank=True)
city = models.CharField(max_length=50, null=True)
state_province = models.CharField(max_length=50, null=True)
zipcode = models.CharField(max_length=10, null=True)
country = models.CharField(max_length=3, default='USA', null=False)
created_at = models.DateTimeField(db_index=True, auto_now_add=True)
updated_at = models.DateTimeField(db_index=True, auto_now=True)
class Meta:
db_table = 'addresses'
and this one.....
class User(models.Model, AbstractBaseUser, PermissionsMixin):
email = models.EmailField(db_index=True, max_length=150, unique=True,
null=False)
first_name = models.CharField(max_length=45, null=False)
last_name = models.CharField(max_length=45, null=False)
mobile_phone = models.CharField(max_length=12, null=True)
profile_image = models.CharField(max_length=150, null=True)
is_staff = models.BooleanField(db_index=True, null=False, default=False)
is_active = models.BooleanField(
_('active'),
default=True,
db_index=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
addresses = models.ManyToManyField(Address),
USERNAME_FIELD = 'email'
objects = MyCustomUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
class Meta:
db_table = 'users'
My first mystery is that by migrating the models, there is no "addresses" field in the users table, nor a pivot table in the database to keep the multiple relationships. How are ManyToMany payloads kept??
Secondly, my goal is to have multiple addresses for Users. I want Users to have multiple "Addresses" (and not each address having one User) because other models can have addresses too. I don't want the Address model to have 12 different "owner" fields with with ForeignKeys.
So. I try this:
from myApp.models import User
from myApp.models import Address
user = User(email="test#test.com", first_name="john", last_name="doe", mobile_phone="444")
# the model permits partial address fields, don't worry about that.
address = Address(city="New York", zipcode="10014")
Now I try to add the address to the user.addresses and I'm getting an error.
user.addresses.add(address)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-0337af6b1cd4> in <module>()
----> 1 user.addresses.add(address)
AttributeError: 'tuple' object has no attribute 'add'
Help?
You have a superfluous comma after the definition of the many-to-many field, which turns it into a tuple. When you've removed this, you'll find both that the migrations will create your intermediary table, and that user.addresses.add() will work.

How do I get related Model field in Django using the Django Admin

I think that my problem here is Django specific and not necessarily a reflection on
my understanding of relational databases (hopefully).
I have a Django app that stores information on Contacts.
With that one table things seemed to work fine. When I wanted to categorize
the type of relationship - is this a professional relationship, family, friends, etc.
That's when things didn't show up like I wanted. I finally got the migration to work
with the new table.
I'm using python 3 with the latest version of django. I have a mysql
database. I want a one to many relationship, where one contact can
be characterized by many categories. When I work with the django admin
and try to enter a contact, I'm not seeing a field for entering relationship categories.
So, here is my models.py for the contacts app.
from django.db import models
class Resource(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
organization = models.CharField(max_length=60, null=True, blank=True)
street_line1 = models.CharField("Street Line 1", max_length=50, null=True, blank=True)
street_line2 = models.CharField("Street Line 2", max_length=50, null=True, blank=True)
city = models.CharField(max_length=40, null=True, blank=True)
state = models.CharField(max_length=40, null=True, blank=True)
zipcode = models.CharField(max_length=20, blank=True, null=True)
phone1 = models.CharField(max_length=20, null=True, blank=True)
phone2 = models.CharField(max_length=20, null=True, blank=True)
email = models.EmailField(max_length=60, null=True, blank=True)
website = models.URLField(max_length=90, null=True, blank=True)
def __str__(self):
return "%s %s \t%s" % (self.first_name, self.last_name, self.organization)
class Meta:
ordering = ('last_name',)
class Relationship(models.Model):
category = models.CharField(max_length=120)
resource = models.ForeignKey(Resource, related_name='category')
def __str__(self):
return self.category
class Meta:
ordering = ('category',)
Thanks in advance for any help,
Bruce

Using two database tables for one control in Django Admin

I am creating a small application to help our Training Department manage their cirriculum using Django. When we talk about students we have two type; Employee and Customer.
Since all of the employees will be in auth_user I would rather not have to populate another table with that data. The behavior that I want is when a Class is displayed in the Django Admin I would like one control to be filled with data from two tables for the student list. Is this even possible in Django. My suspicion is that it is not. This is what I am messing around with:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
cell_phone = models.CharField(max_length=14)
class Meta:
abstract = True
class EmployeeStudent(models.Model, Student):
user = models.OneToOneField(User)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class CustomerStudent(models.Model, Student):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
email = models.CharField(max_length=25)
However, just thinking about it does it make more sense to do:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
user = models.ForeignKey(User, null=True, blank=True, default=None)
first_name = models.CharField(max_length=25, null=True, blank=True, default=None)
last_name = models.CharField(max_length=25, null=True, blank=True, default=None)
email = models.CharField(max_length=25, null=True, blank=True, default=None)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
I cringe at the thought of a blank record.
Any recommendations? Does it make sense to add everything to auth_user and leave the staff flag to false then just use a one to one field to map an auth_user to a Student? I do not really want to do that if I don't have to because I am not going to give anyone else access to the auth_user table so all additions to this table would need to be done by me.
You could try to use model inheritance (i.e User model inheritance : https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-user) for your Student model, or mixing Student(models.Model) with User in your EmployeeStudent and CustomerStudent models :
class Student(models.Model):
cell_phone = models.CharField(max_length=14)
class Meta:
abstract = True
class EmployeeStudent(User, Student):
user = models.OneToOneField(User)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class CustomerStudent(User, Student):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
email = models.CharField(max_length=25)
or :
class Student(User):
cell_phone = models.CharField(max_length=14)
class Meta:
abstract = True
class EmployeeStudent(models.Model):
user = models.OneToOneField(Student)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class CustomerStudent(models.Model):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=25)
email = models.CharField(max_length=25)
If I understand correctly, you'd then want to display Customers as well as Employees in the same changelist in admin ? Using Student(User) with Employee / Customer as inlines might solve your problem.
Hope this helps,
Regards
This is a fairly common use-case (i.e. different types of userprofiles) in Django. In your case, I think the approach below would suit your scenario:
from django.db import models
from django.contrib.auth.models import User
class Student(models.Model):
STUDENT_TYPES = (
('E', 'EmployeeStudent'),
('C', 'CustomerStudent'),
)
user = models.OneToOneField(User, null=True, blank=True, default=None)
user_type = models.CharField(max_length=1, choices=STUDENT_TYPES)
class EmployeeDetails(models.Model):
student = models.OneToOneField(Student)
extension = models.CharField(max_length=4, null=True, blank=True, default=None)
class StudentDetails(models.Model):
student = models.OneToOneField(Student)
# BTW: all the fields below are redundant since they are already in User
first_name = models.CharField(max_length=25, null=True, blank=True, default=None)
last_name = models.CharField(max_length=25, null=True, blank=True, default=None)
email = models.CharField(max_length=25, null=True, blank=True, default=None)
This way, you can check the student.user_type and infer if you need to get EmployeeDetails or StudentDetails
NOTE:: Even though this is a recommended approach, it is not quite easy to enter data using the default admin interface in this manner. You might want to see how profile inlines are done to show the user profile fields in the admin as well.