how to add field to `auth_user_groups` table in django? - django

In my Django project I have users that every user may have different permission (some one has only read permission but others may be both read and write permissions) I want to add permissions field to django auth_user_groups table like this:
here is my models.py:
from django.db.models import *
from django.contrib.auth.models import User, Group
from django.db.models.signals import post_save
class MyUser(Model):
user = OneToOneField(User, primary_key=True)
Volume = IntegerField(default=5*1024*1024)
def create_profile(sender, instance, created, **kwargs):
if created:
profile, created = MyUser.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User, dispatch_uid="create_profile")
is it possible to do that ?

I would recommend you to create an additional table with an one-to-one relationship to auth_user_groups to solve your issue rather than fiddling with that. This is a similar approach as the one suggested in the docs. Alternatively you would have to do a lot of work in order to provide your own models.
EDIT: Following up on the first comment: It is not possible to expose this model as the respective many-to-many field of the User model does not use an explicit intermediate model (in fact the many-to-many field belongs to PermissionsMixin, from which AbstractUser is derived, from which User is derived).
An one-to-one field is essentially a many-to-one foreign key with unique=True. Therefore, you could instead create two foreign keys, one for User and one for Group with unique_together and then use these.

Django provides permission to to group of users and individual users, You can create multiple groups and assign permissions to those groups. And assign groups to each user. So user withina a particular group will have same set of permissions.
Refer here for more https://docs.djangoproject.com/en/1.8/topics/auth/default/#permissions-and-authorization

Related

How to design the user table in database?

I want to develop a server side of an app that holds users.
Of course I need a table in database holding the user information.
At first I may write
class User(models.Model): # using django models
userid = ...
password = ...
which gives me a database table containing userid and password.
However, I might want to add some attributes (maybe Credit, Birthday...so on) to each user in the future. I just can't think up all of them right now. And I can't know what attributes I would really need in the future.
How can I deal with it?
There's already a user table in Django. This table is automatically create when you first apply the migration with 'manage.py migrate' command.
In database schema, this table is listed as auth_user and you can import it into Django with the following command
from django.contrib.auth.models import User
Django provides a default model for User. you can use it like this.
from django.contrib.auth.models import User
and as per your second query. you can do so by creating another model and adding a ForeignKey or OneToOneField of User model to link it with each user.
class Customuserprofile(models.Model):
user=models.OneToOneField(settings.AUTH_USER_MODEL)
credit=models.CharField()
birthday=models.DateTimeField()
well, if you want to add some field to the User you can use AbstractUser or AbstractBaseUser model read this that explain the differences and give a example https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#abstractbaseuser

In django, for a user, get all objects which ForeignKey to groups he/she belongs to (efficiently)

I have 3 models, User, Group and Exam:
from django.db import models
from django.contrib.auth.models import User, Group
class Exam(models.Model):
# a lot of fields
solutions_group = models.ForeignKey(Group)
For an instance user of model User I want to get all Exams in whose solutions_group user belongs.
This is what I thought of:
exam_list = []
for group in user.groups.all():
exam_list+= list(group.exam_set.all())
But this involves multiple database queries.
Is there a better way to do this, involving lesses queries?
I'm using Python 3.4 and Django 1.8.
Try filtering on Exam.objects using an "in" filter
user_groups = user.groups.all()
user_exams = Exam.objects.filter(solutions_group__in=user_groups)
I think you can also use the related_name from group to user (user_set) using the following query:
user_exams = Exam.objects.filter(solutions_group__user_set=user)

How to sync OnetoOne relation in CreateView

models:
class Book(models.Model):
name = models.Char()
class BookCount(models.Model):
book = OneToOneField(Book)
count = SmallIntegerField(default=0)
views:
class BookCreate(CreateView):
model = Application
The question is, after create Book, I want insert a record to BookCount. Any ideas?
If your BookCount model is required you could use a listener for the post_save signal along the lines of this:
# models.py
from django.db.models.signals import post_save
# Model definitions
...
def create_book_count(sender, instance, created, **kwargs):
if created:
BookCount.objects.create(book=instance)
post_save.connect(create_book_count, sender=Book)
If your models are really this simple, you may want to drop the BookCount model and add a count field to your Book model instead to reduce the complexity and overhead here. See the docs on extending the user model for a short overview of why it might be better to avoid the OneToOneField option (the wording is specific to the User model, but it applies here, too):
Note that using related models results in additional queries or joins to retrieve the related data, and depending on your needs substituting the User model and adding the related fields may be your better option. However existing links to the default User model within your project’s apps may justify the extra database load.

Django get the value of foreignId from django.contrib.auth.models User

I have created a model which has foreign key to the django.contrib.auth.models User model. I need to retrieve the value the foreign key is referring to. But how to do that?
E.g. my model is
from django.contrib.auth.models import User
def FooModel(models.Model):
user = models.ForeignKey(User)
then I know I can either use:
FooModel.objects.get() or FooModel.objects.filter() but as far as I know they will only return entries from the FooModel only. So how do I retrieve from the User model?
m = FooModel.objects.get(id=123434)
m.user.username
You can use ..That wxample will return you the username of the related user. Also you can create joins using __ on the query filtering. Like:
FooModel.objects.get(user__username='Foo')
But, since you are building your query on FooModel, you will always get FooModel results. So you have you use . to use foreignkey relations to get to the required User field.
EDIT:
Django also allows you to use reverse relations on querysets, so even though User model do not have a foreignkey to FooModel on its model structure, you can use reverse relation of Foomodel.user foreignkey like:
def FooModel(models.Model):
user = models.ForeignKey(User)
foofield = Models.CharField(...)
User.objects.get(foomodel__foofield='Beatles')
will return you the user which have FooModel record with a foreign key to his User record and foofield value of Beatles
You can access foreign key ids by referencing the property name + _id. For example: yourmodel.user_id

How to create a permissions table independent of the user permissions in Django?

I want to create a permission table that takes django-users and another table as its foreign key . And then gives permissions to it . What should be there in models.py ?
The doubt can be put across as two separate questions :
How to use django-users (user id) as a foreign key in another app called
permissions .
How to use table-id that is generated by django when syncdb is
done as the priamry key of
that table (Different app) , to be used as foreign key of this app permissions .
Is there a reason you can't use the permissions features in django.contrib.auth? By using the permissions feature of the Meta object and the Groups table, you can easily create a matrix of "users in group X may perform action Y".
The more I think about this, the more it seems that your implementation would mirror the Groups/permissions feature without extra benefits.
See https://docs.djangoproject.com/en/1.3/topics/auth/ for details.
Your best best is to create a User Profile - which is a model that can be linked to the User model, where the Profile model contains whatever keys you want. Then you can call User.get_profile(), and get a model object, check what keys it has.
For the model, you want to look at the ContentTypes app in .contrib. (https://docs.djangoproject.com/en/1.3/ref/contrib/contenttypes/) and you can just create a foreign key to the user.
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
class Permission(models.Model):
user = models.ForeignKey(User)
table = models.ForeignKey(ContentType)
### the rest of the model.
Then in your view or whatever:
perm = Permission()
perm.user = request.user
perm.table = ContentType.objects.get_for_model(TableToAddPermissionFor)
perm.save()