I have the following User object,
class User(AbstractBaseUser, PermissionsMixin, Base):
username = models.CharField(
db_index=True,
null=False,
unique=True,
max_length=255,
)
mobile = PhoneNumberField(
db_index=True,
null=False,
unique=True,
)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
And I've the following class to manage connections,
class Connections(Base):
owner = models.OneToOneField(
User,
on_delete=models.CASCADE,
null=True,
)
friends = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='friend_set',
null=True,
blank=True,
)
followers = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='follower_set',
null=True,
blank=True,
)
followings = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='following_set',
null=True,
blank=True,
)
When I try to add a friend,
sender = User.objects.get(
id=kwargs.get('sender_id')
)
receiver = User.objects.get(
id=kwargs.get('receiver_id')
)
sender_connections, created =(
Connections.objects.get_or_create(owner=sender)
)
sender_connections.friends.add(receiver)
I get the following error,
'NoneType' object has no attribute 'add'
Can someone help me with this?
It looks like you are trying to user the django related manager add function
sender_connections.friends.add(receiver)
However the friends attribute on connections is a ForeignKey relation instead of a ManyToManyField. This means that when you call sender_connections.friends and the connection does not exist, you will get None.
If you change the attribute to a ManyToManyField, then sender_connections.friends will return a ManyRelatedManager and the add should work as expected.
Complementing the wingardtw answer, with Django 3.0 you can use PrimaryKeyRelatedField, and instead of using "add" you will perform an update on the queryset, like under:
Connections.objects.filter(owner=sender).update(friends=receiver)
Important: This requires the objects to already be saved.
See those link for more information:
https://docs.djangoproject.com/en/3.0/ref/models/relations/#django.db.models.fields.related.RelatedManager.add
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.query.QuerySet.update
Related
I ahve a user model called TbUser and I have integrated a mysql legacy database with django. After doing migrations I have the follwing tables. django_seesion, django_migrations, django_content_type, django_admin_log, auth_permission, auth_group_permissions, auth_group
When I log in to django admin page, and click on the TbUser then select a random user I am getting the following error.
Exception Value:
(1146, "Table 'db.tb_user_groups' doesn't exist")
Should this table be created when migrations are run?
Could it be that this table is the auth_group, and django is looking for this one using the wrong table name?
users.models
class TbUser(AbstractBaseUser, PermissionsMixin):
id = models.CharField(primary_key=True, max_length=32, default=uuid.uuid4)
username = models.CharField(
max_length=40, blank=True, null=True, unique=True, db_column='usname')
password = models.CharField(
max_length=255, blank=True, null=True, db_column='psword')
email = models.CharField(max_length=255, blank=True, null=True)
role = models.ForeignKey(TbRole, on_delete=models.CASCADE)
department = models.ForeignKey(
'app.TbDepartment', on_delete=models.CASCADE, null=True, blank=True)
is_superuser = models.BooleanField(
default=False, blank=True, null=True, db_column='default_super')
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
objects = TbUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
managed = False
db_table = 'tb_user'
admin.py
from app.models import TbDepartment
from django.contrib import admin
from .models import TbCustomer, TbRole, TbUser, TbUserRole
admin.site.register(TbUser)
admin.site.register(TbRole)
admin.site.register(TbUserRole)
admin.site.register(TbDepartment)
admin.site.register(TbCustomer)
UPDATE:
I have created in mysql a table called tb_user_groups and when doing the same action the next error appears
Exception Value:
(1146, "Table 'db.tb_user_user_permissions' doesn't exist")
How do I generate these tables?
Why don't you just use AbstractUser. It has everything configured, and you can customize it if you want. In this case you shouldn't get tb_user_groups doesn't exist error.
class TbUser(AbstractUser):
REQUIRED_FIELDS = []
objects = TbUserManager()
I have the following custom user model arrangement.
```
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
class StudentProfile(models.Model):
student = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
location = models.CharField(max_length=8, blank=False, default='')
class TeacherProfile(models.Model):
teacher = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
location = models.CharField(max_length=8, blank=False, default='')
gender = models.CharField(max_length=8, choices=GENDER_CHOICES, default='')
```
I am able to a query the students based on the location of their teacher (current user).
Student.objects.filter(location=request.user.teacher.location)
I can also query the user model & find all teachers/students
User.objects.filter(is_teacher=True)
QUESTION:
Without relying on the profile models (Student & Teacher) How can I extend the query on abstractuser using profile attributes.
[X]-This is wrong but the idea is something like;
User.objects.filter(is_teacher=True).filter(is_teacher.location=newyork)
You can follow the OneToOneField in reverse:
User.objects.filter(teacherprofile__location='newyork')
You thus do not need to store is_teacher and is_student explicitly. You can simply filter Students with:
# Users with a related StudentProfile record
User.objects.filter(studentprofile__isnull=False)
Model:
class Comment(models.Model, CharField, ListField):
user = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='comment_user',
blank=True, null=True)
news = models.ForeignKey(News, related_name='comment_of', on_delete=models.CASCADE)
content = models.CharField(validators=[MinLengthValidator(4)], max_length=200")
parent_comment = models.ForeignKey('self', blank=True, null=True, related_name='parent',
on_delete=models.CASCADE)
class Meta:
ordering = ['-created']
def __str__(self):
return self.content
When I login in admin click comment,there is an error:
Direct assignment to the reverse side of a related set is prohibited. Use parent.set() instead.
When I remove:
parent_comment = models.ForeignKey('self', blank=True, null=True, related_name='parent',
on_delete=models.CASCADE)
The error gone.
So,how to modify parent_comment,I think the issue is here.
This question already has an answer here:
How to query related models in django models.py
(1 answer)
Closed 3 years ago.
I have a model called StudentProfile:
class StudentProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
class_advisor = models.CharField(max_length=50)
year = models.OneToOneField(YearLevel, on_delete=models.SET_NULL, null=True)
section = models.OneToOneField(Section, on_delete=models.SET_NULL, null=True)
what I want to happen is, class_advisor to only return and accpet User with is_teacher = True.
by the way here's my User model:
class User(AbstractUser):
email = models.EmailField(
max_length=254,
unique=True,
verbose_name='Email Address',
blank=True
)
is_student = models.BooleanField(default=False, verbose_name='Student')
is_superuser = models.BooleanField(default=False, verbose_name='Administrator')
is_teacher = models.BooleanField(default=False, verbose_name='Teacher')
is_staff = models.BooleanField(default=False, verbose_name='Staff')
is_registrar = models.BooleanField(default=False, verbose_name='Registrar')
Yes, however at the moment, something is wrong with your modeling. You should make class_advisor a ForeignKey to the user model. Imagine that you store the username (or whatever unique attribute of that user) in your model. If later that teacher changes that username, then it will refer to a non-existing user, or later to a different user that picked the username.
You can set the limit_choices_to=... parameter [Django-doc]:
from django.db.models import Q
from django.contrib.auth import get_user_model
class StudentProfile(models.Model):
user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, primary_key=True, related_name='studentprofile')
class_advisor = models.ForeignKey(get_user_model(), limit_choices_to=Q(is_teacher=True), related_name='students')
year = models.OneToOneField(YearLevel, on_delete=models.SET_NULL, null=True)
section = models.OneToOneField(Section, on_delete=models.SET_NULL, null=True)
If you use forms, etc. It will limit the options to Users that are teachers, and do validation on this.
It is better to use get_user_model() [Django-doc] here to refer to your user model, since if you later alter it, the ForeignKey (and OneToOneField will refer to the new model).
Try this:
StudentProfile.objects.filter(user__is_teacher=True)
StudentProfile.objects.filter(user__is_teacher=True).values('class_advisor')
I have followed these [1,2,3] links to create a custom user model by extending AbstractBaseUser class. I am storing login information of three type of users lets say teacher, Admin and students in this table. USERNAME field is emailId.
I want to make emailId unique among one type of users. In other words, in my system student can register as teacher as well with same emailId. But since emailId is USERNAME field and hence unique, I am unable to achieve this.
Please suggest how can I do this in Django application.
UserModel :
class UserModel(AbstractBaseUser):
user_type_choices = (
(constants.USER_TYPE_ADMIN, 'Admin'),
(constants.USER_TYPE_INSTITUTE, 'Institute'),
(constants.USER_TYPE_STUDENT, 'Student')
)
sys_id = models.AutoField(primary_key=True, blank=True)
name = models.CharField(max_length=127, null=False, blank=False)
email = models.EmailField(max_length=127, unique=True, null=False, blank=False)
mobile = models.CharField(max_length=10, unique=True, null=False, blank=False)
user_type = models.PositiveSmallIntegerField(choices=user_type_choices, null=False, blank=True)
is_staff = models.BooleanField()
is_active = models.BooleanField(default=True)
objects = MyUserManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ['name', 'mobile', 'user_type','is_staff']
I am using other models like StudentsDetails, TeacherDetails with foreign key to UserModel to store extra information.