Use Django User permission layout for other manytomany field - python

When in a User object in the Django Admin, there is a really nice way to add permissions to the user.
For a completely different model, I would like to use the same system. This model has a manytomany field to another model. Is there a way to copy the layout of the user admin, to this model's admin?

Add your field to the ModelAdmin's filter_horizontal:
#admin.register(MyModel)
class MyModelAdmin(ModelAdmin):
# ...
filter_horizontal = ['my_many_to_many_field']

Related

Django Admin register ManyToMany intermediate model

I create the following models:
class Child(models.Model):
some_var = models.CharField()
class Parent(models.Model):
m2m = models.ManyToManyField(Child)
Django automatically creates an intermediary model in the background called ParentChild. Now, I would like to register that intermediary model in the Django Admin. Is that possible? If so, how? Or does it only work with through="ThroughModel"?
You have to use through Model for this.
Basically Django create only intermediate table in db, not model. So you need to define Model class to register it in the Admin.
https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#working-with-many-to-many-intermediary-models

Django: when to use OneToOneField and when use Inheritance? [duplicate]

I want to implement users in my system. I know that Django already has an authentication system, and I've been reading the documentation. But I don't know yet the difference between
from django.contrib.auth.models import User
class Profile(User):
# others fields
And
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# others fields
I don't want to know why to use one or another, but what happens under the hoods. What's the difference?
Your first example is multi-table inheritance.
class Profile(User):
If you have a profile, you can access all the fields on the user model directly (e.g. profile.username and profile.email). In this case, Django creates a OneToOneField for you automatically.
The second example is a regular OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User)
In this case, you cannot access profile.username and profile.email. Instead, you access these fields via the one to one field (e.g. profile.user.username and profile.user.email).
In your case, where you are adding a profile model, I would avoid using inheritance, and use a one to one field instead. The User model has custom admins to handle passwords. If you use multi-table inheritance, then your Profile model would have to handle this as well. By using a one-to-one field, the custom admins can handle the user fields, and your Profile model admins only have to handle the additional profile fields.
Another option is creating a custom user model. In this case you subclass an abstract class AbstractUser or AbstractBaseUser instead of the class User. If your Profile class works, then I would recommend this instead of the custom user model, because custom user models are more complicated to set up.

Under the hoods what's the difference between subclassing the user and creating a one to one field?

I want to implement users in my system. I know that Django already has an authentication system, and I've been reading the documentation. But I don't know yet the difference between
from django.contrib.auth.models import User
class Profile(User):
# others fields
And
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# others fields
I don't want to know why to use one or another, but what happens under the hoods. What's the difference?
Your first example is multi-table inheritance.
class Profile(User):
If you have a profile, you can access all the fields on the user model directly (e.g. profile.username and profile.email). In this case, Django creates a OneToOneField for you automatically.
The second example is a regular OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User)
In this case, you cannot access profile.username and profile.email. Instead, you access these fields via the one to one field (e.g. profile.user.username and profile.user.email).
In your case, where you are adding a profile model, I would avoid using inheritance, and use a one to one field instead. The User model has custom admins to handle passwords. If you use multi-table inheritance, then your Profile model would have to handle this as well. By using a one-to-one field, the custom admins can handle the user fields, and your Profile model admins only have to handle the additional profile fields.
Another option is creating a custom user model. In this case you subclass an abstract class AbstractUser or AbstractBaseUser instead of the class User. If your Profile class works, then I would recommend this instead of the custom user model, because custom user models are more complicated to set up.

django-oauth2-provider with custom user model?

I am really stuck in my project right now. I am trying to implement Oauth2 for my app. I found out about django-oauth2-provider a lot and tried it. The only problem is, it uses the User model at django.contrib.auth. The main users of our site are saved in a custom model called User which does not inherit from or extend the model at django.contrib.auth.
Is there any way to use my custom User model for creating clients and token?
If django-oauth2-provider can't be used for this purpose, can anyone recommend me some oauth2 library with the option to implement oauth2 with my own model.
Sincerely,
Sushant Karki
As the previous answer suggested, you should extend AbstractUser from django.contrib.auth.models.
The problem with the access token that the OP referring to, occur when changing the setting AUTH_USER_MODEL AFTER django-oauth2-provider was migrated.
When django-oauth2-provider is migrated, it creates a key constrain between the User model and django-oauth2-provider.
The solution is very easy:
Create your new User model and change the AUTH_USER_MODEL setting.
Go to the django_migration table in your database.
Delete all rows of django-oauth2-provider.
run python manage.py makemigrations
run python manage.py migrate
Now, the django-oauth2-provider tables are connected to the RIGHT User model.
django-oauth2-provider fetches the user model using settings.AUTH_USER_MODEL, with a fallback to auth.User. If you extend AbstractUser your User model will include all the fields of auth.User plus any additional fields you specify.
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
some_additional_field = models.BooleanField(default=False)
Specify the user model to be used like this in settings.py:
AUTH_USER_MODEL = 'user_api.User'
If you don't want to base your user on AbstractUser you'll also need to write your own user manager, e.g. by extending the BaseUserManager
You can read more about ways to customize django's user model here.

Customizing the Django User admin

I have a Django application where users have additional data. That data is collected in a Profile model with a OneToOneField pointing to User.
This is fine and works perfectly for most purposes, but I have trouble customizing the admin for User. In particular:
I would like to be able to show a Profile field inside list_display. I don't know how to do this without writing an additional method on User itself.
I would like to be able to show some information about related models (e.g. some resources owned by the user) inside the User detail page. Again, I do not know how to do this without writing a custom User method.
Do you know any solution to the above?
You only have to edit the admin classes in admin.py. You can use admin.inline* class to help you. Example from Django website that will add Book to the Author's admin page:
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
admin.site.register(Author, AuthorAdmin)
Read more here.
EDIT: You should be able to add methods on UserAdmin model and refer to them when setting the list_display fields:
list_display = (..., 'your_method')
Turns out, one can put the methods in the UserAdmin itself instead than in the User model. This way I can access all the information I need about the user.

Categories