Django Foreign Key Relations - django

I am trying to make relationship between two tables, Registered_Users and User_Connections, so that those who are registered can add others in their connection list(more like add friends). Following are contents from models.py:
class Registered_Users(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField(unique=True)
password = models.CharField(max_length=10)
def __unicode__(self):
return self.email
class User_Connections(models.Model):
email = models.EmailField(blank=True)
connection_email = models.EmailField(blank=True)
user_connection = models.ForeignKey(Registered_Users, null=True)
def __unicode__(self):
return self.connection_email
What I am trying to do is:
get a registered user:
ru = Registered_Users.objects.get(id=1)
get this registered user's connections from User_Connection:
uc = User_Connections.objects.filter(user_connection=ru)
Now how can I display user connections' email id from User_Connection and first_name for each user connection from Registered_Users.
Let me know if there's a better way to achieve this.
NOTE: user connections' email id will also be present in Registered_Users because all the email ids must be registered.
Appreciate any help. Thanks.

class RegisteredUser(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField(unique=True)
password = models.CharField(max_length=10)
connected_users = models.ManyToManyField('self', blank=True, symmetrical=False)
def __unicode__(self):
return self.email
the api now looks like this:
ru = RegisteredUser.objects.get(id=1)
another_user = RegisteredUser.objects.get(email='name#example.com')
ru.connected_users.add(another_user)
uc = ru.connected_users.all()
for user in uc:
print user.first_name, user.last_name, user.email

The Best way to Implement friendship is to use ManyToManyField in Django:
You can read more about it here: https://docs.djangoproject.com/en/1.6/ref/models/fields/#ref-manytomany
Also, to resolve you confusion about query, with 'uc' variable you can just do:
uc.email for email id
and
uc.user_connection.first_name for firstname .
You can read More about Django Queries and objects here : https://docs.djangoproject.com/en/1.6/topics/db/queries/

Related

Fetching data from models using OneToOneField in Django

well my college is making us go learn a framework and make a website with it in a month, and it's really killing me, because of that I couldn't really get a good understanding of the Django framework as I am making progress while watching YouTube vids and reading docs.
Anyways my models are all messed up which made the job even harder, and whenever I solve a problem another one arises, but the deadline is close and making any changes to the models will cost me a great deal of time. This time my problem is about fetching data.
The concerned models are the following:
The User class for authentication
class User(AbstractBaseUser, PermissionsMixin):
id = models.AutoField(primary_key=True,null=False)
username = models.CharField(max_length=50)
email = models.EmailField(unique=True)
nom = models.CharField(max_length=255)
prenom = models.CharField(max_length=255)
usertype = models.CharField(choices=types,max_length=20,default="user")
date_joined = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now=True)
is_superuser = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
student_data = models.OneToOneField(Etudiant, on_delete=models.CASCADE,blank=True, null=True,related_name='Etudiant_access')
Prof_data = models.OneToOneField(Prof, on_delete=models.CASCADE,blank=True, null=True)
objects=UserManager()
def __str__(self):
return self.prenom + " " + self.nom
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
The Students(Etudiant) class for managing the students:
class Etudiant(models.Model):
filiere = models.ForeignKey(Filiere, on_delete=models.DO_NOTHING)
classe = models.ForeignKey(Classe,null=True, on_delete=models.DO_NOTHING)
notes = models.ManyToManyField(note,blank=True, null=True)
The class Classe (LMAO) for managing the different classes:
class Classe(models.Model):
#Cla_id = models.AutoField(primary_key=True, null=False)
Designation = models.CharField(max_length=100)
filiere = models.ForeignKey(Filiere, on_delete=models.CASCADE)
Epreuve = models.ManyToManyField(Epreuve,blank=True, null=True)
def __str__(self):
return self.Designation
The thing is that I wanna fetch all data of the Users that are students (which means that their Prof_data attribute is blank/null and their student_data attribute is pointing to the Etudiant(Student) class while having an Etudiant.classe attribute equals to a value in the view's parameters
I've solved a great deal of it but I'm stuck at the end
This is my view function:
#login_required
def class_info(request,design):
#getting the Classe(s) from the url which Designation == design
classe_now = Classe.objects.get(Designation=design)
print(classe_now) # This works like a charm
#getting the Students objects that are part of the class_now
Etudiants = Etudiant.objects.filter(classe=classe_now)
print(Etudiants) # This works too. It returns the 'Etudiant' objects from where i wanna access to the Users data
#getting the User data of the student objects (This is where i get confused)
students_to_show = User.objects.filter(student_data=Etudiants)
pprint(students_to_show)
return render(request, 'Prof/class_info.html')
I am really confused, you are truly my last hope in this, and thank you for your time.
You can filter your User model by selecting all users that do have empty/null relation to Prof model and nonempty/null relation to Etudiant model.
student_users = User.objects.filter(Prof_data__isnull=True, student_data__isnull=False)
then for each stident_user, you can fetch its student data in the following manner:
student_user = student_users[0]
student_user.student_data.filiere
student_user.student_data.classe
student_user.student_data.notes
You can then pass the queryset result to the render function as a context variable. Check this brief tutorial on how to pass data to templates.

How to delete the reference object that will not delete the referred object in Django?

Here I've two models. one is Contact and another one is Sent_replies. If client wants to contact with admin his information will be stored in Contact model. So here I want that if admin replies to that client, that specific information will be deleted from Contact model without deleting the record which is in Sent_replies. How can I do that.
models.py
class Contact(models.Model):
message_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
phone = models.CharField(max_length=100)
comment = models.TextField(max_length=100)
date = models.DateField()
def __str__(self):
return self.name
class Sent_replies(models.Model):
message = models.ForeignKey(Contact,on_delete=models.CASCADE, null=True)
subject = models.TextField(max_length=100)
reply = models.TextField(max_length=500)
def __str__(self):
return self.message.name
First add a new field is_deleted that can be marked as True for replied message and False for not replied yet message
class Contact(models.Model):
message_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
phone = models.CharField(max_length=100)
comment = models.TextField(max_length=100)
date = models.DateField()
is_deleted = models.BooleanField(default=False) #new
def __str__(self):
return self.name
now every time you created a sent_replie you can marked it as is_deleted = True that method is called soft deletion
To filter which message are not yet replied you can do this
not_replied = Contact.objects.filter(is_deleted=False)
Do not forget to make migrations and migrate and if you have a question please let me know.
If I understand correctly what you want to archive...
I would suggest making third model called for example ContactRequest.
It will have foreign key to Contact which will store contact informations.
Then after admin reply to ContactRequest you can link reference to Contact instance in Sent_replies and delete ContactRequest instance instead.
Then the message set be set to NULL
message = models.ForeignKey(Contact,on_delete=models.SET_NULL, null=True)

How to search for objects in the Django User model

I have a Profile model:
from django.contrib.auth.models import User
class Profile(models.Model):
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
birthday = models.DateField(null=True, blank=True)
bio = models.TextField(blank=True, max_length=1000)
location = models.CharField(max_length=100, blank=True)
...
And a search contacts view:
class SearchContactsView(ListView):
model = Profile
template_name = 'users/contact_search.html'
context_object_name = 'qs'
def get_queryset(self):
q1 = self.request.GET.get('contact_name')
q2 = self.request.GET.get('contact_location')
if q1 or q2:
return Profile.objects.filter(Q(first_name__icontains=q1) |
Q(last_name__icontains=q1),
location__icontains=q2)
return Profile.objects.all()
It is working fine but I would like to be able to search for contacts via the user field as well. Does anyone know a way to do that?
EDIT my user's username's are created by them when they sign up to the site and are currently uneditable. They are displayed on the admin page via a dropdown since they are a OneToOneField. I think my issue is that django recognises them only as an IntegerField('pk') but I need to somehow cast them as a string value. Am I right in thinking that, and if so how can this be achieved?
You can add to your template to allow user to input user_username and save that username to q3:
q3 = self.request.GET.get('user_username')
After that you can adjust your If condition accordingly, then change your return to something like:
Profile.objects.filter(Q(first_name__icontains=q1) |
Q(last_name__icontains=q1),
location__icontains=q2,
user__username=q3)

Get the records by joining three table that are not in another table

I'm trying the get the records from the Student table, condition is that the student's primary key do not exist in the From table.(From is used as a relation) table.
Relation is "student from department"
Model:
class Student(models.Model):
name = models.CharField(max_length=20)
password = models.CharField(max_length=30)
phone_no = PhoneNumberField(null=False, blank=False, unique=True)
email = models.EmailField()
pic_location = models.FileField()
username = models.CharField(max_length=30)
class From(models.Model):
s = models.ForeignKey(Student, on_delete=models.PROTECT)
d = models.ForeignKey(Department,on_delete=models.PROTECT)
class Department(models.Model):
name = models.CharField(max_length=20)
password = models.CharField(max_length=30)
phone_no = PhoneNumberField(null=False, blank=False, unique=True)
email = models.EmailField()
I'm trying to get those records in the list view. And please review whether the way i'm retrieving session variable is good to go in such case??
class PendingStudent(ListView):
# Students pending for department approval
context_object_name = 'pending_students'
model = From
template_name = "admin_panel/department/student_detail.html"
def get_queryset(self):
department = self.request.session.get('username')
return From.objects.filter(~Q(d__name==department))
I've used session, to store what type of user is logged in (student/teacher/department).
It seems that you want to return a queryset which excludes certain values. For that I'd use .exclude() instead of filter since it's more explict.
You can check that here
def get_queryset(self):
department = self.request.session.get('username')
queryset = From.objects.exclude(d__name=department)
# In order to print the SQL query you can do this below
# print(queryset.query.__str__())
return queryset
However, if you want to return many students who are not in the From the table you could do something like:
def get_queryset(self):
return Student.objects.filter(from__d__isnull=True)
You can check that here

Saving to database with one query

I have standard django User model and I have an extended model Member. The Member model is connected to Subscription model.
class Type(models.Model):
limit = models.IntegerField()
name = models.CharField(max_length=50)
default = models.BooleanField()
def __str__(self):
return self.name
class Subscription(models.Model):
started = models.DateField()
type = models.OneToOneField(Type)
def __str__(self):
return self.type.name
class Member(models.Model):
user = models.ForeignKey(to=User)
number = models.CharField(max_length=10)
match_code = models.CharField(max_length=50)
parent = models.ForeignKey("self", null=True, blank=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=255)
postcode = models.CharField(max_length=10)
city = models.CharField(max_length=100)
country = models.ForeignKey(to=Country, null=True)
language = models.ForeignKey(to=Language)
telephone = models.CharField(max_length=50)
mobile = models.CharField(max_length=50)
main_email = models.EmailField(null=True, blank=True)
active = models.BooleanField()
subscription = models.ForeignKey(Subscription)
def __str__(self):
return self.name
When I create a new user, and when I want to save it to database I do it as follows :
language = Language.objects.get(key="EN")
country = Country.objects.get(key="BE")
# Add to user model
user = User()
user.username = request.POST['email']
user.first_name = request.POST['firstname']
user.last_name = request.POST['lastname']
user.email = request.POST['email']
user.set_password(request.POST['password'])
user.save()
# Add subscription
subscription = Subscription()
subscription.started = datetime.date.today()
subscription.type = Type.objects.filter(default=True)
last_subscription = Subscription.objects.all().order_by('-id')[0]
# Get the last field from user model
last_user = User.objects.all().order_by('-id')[0]
# Add to member model with the last user
member = Member()
member.number = request.POST['member_id']
member.address = request.POST['address']
member.postcode = request.POST['postcode']
member.city = request.POST['city']
member.country = country
member.telephone = request.POST['telephone']
member.mobile = request.POST['mobile']
member.user = last_user
member.language = language
member.active = False
member.subscription = last_subscription
member.save()
But I think that I hit the database to many times. Is there any better solution to do it? Can it be done maybe with one query?
Several things wrong here
subscription.type = Type.objects.filter(default=True)
You are asigning a whole queryset to subscription.type this code would produce an error here. Secondly don't use default as a model field name.
last_subscription = Subscription.objects.all().order_by('-id')[0]
Not quite sure what you are trying to do here. The efficient and error free approach would be to save the subscription object and use it's generated id for your next operation.
user.username = request.POST['email']
user.first_name = request.POST['firstname']
user.last_name = request.POST['lastname']
user.email = request.POST['email']
user.set_password(request.POST['password'])
It's not a good idea to directly pass in post data to models. You should use django forms to validate them first.
last_user = User.objects.all().order_by('-id')[0]
# Add to member model with the last user
This may or may not be the user that you just saved. It's very likely that another instance would have saved another user just after this thread did. It's safer to use user.id (as already mentioned regarding subscription)
Actually, you don't need to get last subscription or last user instance. You can(and should!) just use your subscription and user objects. Because they will have id after the save method will be called."Auto-incrementing primary keys"
Also, it seems that you've never saved the subscription instance.