Auto-populating user manytomanyfield with Django admin site - django

I have a class Business, example:
class Business(models.Model):
users = models.ManyToManyField(User)
business_name = models.CharField(max_length=100)
So the variable users in connected with the User. And let's assume that in the User, there are 5 users were created: Admin, Test, Test1, Test2 and Test3. So only Admin is the superuser of all the users and let's say that I am logged in using Test2. So when I clicked save, the manytomanyfield will be automatically saved with Test2, so it is like automatically saved on whoever the request.user is.
And also, is there a way to automatically save all the users in the manytomanyfield? thanks.

You don't need to use JavaScript for this, neither do you need to show a form field for users if it's meant to be automatically updated. You can instead create a ModelAdmin subclass and override the save_model method. For example:
In the admin.py of your app
from django.contrib import admin
from models import Business
class BusinessAdmin(admin.ModelAdmin):
exclude = ["users"]
def save_model(self, request, obj, form, change):
if not obj.id: obj.save()
obj.users.add(request.user)
obj.save()
admin.site.register(Business, BusinessAdmin)

Related

Send E-mail to User When Account is Activated though Django Admin Application

Is there a way to send an e-mail to a user when their account is activated through the Django admin application? I can do it independently of the Django admin application but I want the admin to be signed in before they activate a user. Is there a way to achieve this without customizing the Django admin application code? Thanks in advance.
Well, you can override the ModelForm and add the email sending logic in clean method. Also use that modelform in the Admin class. For example:
class UserForm(forms.ModelForm):
manual_activation = forms.BooleanField() # a flag which determines if the user should be manually activated
class Meta:
model = User
fields = '__all__'
def clean(self):
manual_activation = self.cleaned_data.pop('manual_activation', False)
if manual_activation:
# send_email logics
return self.cleaned_data
class UserAdmin(admin.ModelAdmin):
form = UserForm
What will happen is that, in the User admin page, if you click on an user it will show an extra field in the form, named manual_activation. If you check and save the form, then in clean method, you can catch the value of manual_activation and based on that send email.

Django: Create staff user from oneToOneField

I have a model in order to extend the user model with some extra fields.
The "therapeut" model has a user field that's a OneToOneField connected to User from django.contrib.auth.models. Here's the code:
from django.db import models
from django.contrib.auth.models import User
class Therapeut(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# some more fields here
Now when I want to add a "therapeut" from the model through the Django Admin, I can choose from the available Users or add a new one.
When click I add a new one (green + next to the User dropdown), I would like that new user to have staff status and add it to the user group "therapeuten", in order to manage the permissions for this new user.
I dont see how to archieve this (automatically), neither do I have the option to set staff status and user group in the popup. Note I am logged in as the superuser. See pic:
Any help on how to do this would be much appreciated!
OK so I figured out how to do it, I'm adding the solution here for reference:
Override the save method on the Therapeut class like so:
class Therapeut(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# some more fields here
# override save method to add staff status to connected user and add it to therapeutengroup
def save(self, *args, **kwargs):
userObj = self.user
userObj.is_staff = True
userObj.save()
therapGroup = Group.objects.get(name='therapeut')
therapGroup.user_set.add(userObj)
super(Therapeut, self).save(*args, **kwargs)
However, if someone else has a better or different solution, More than welcome to suggest it here!

Django Custom Permission for Authorization

I am working on a Django Project, where one model (lets say Document) has the following field:
#In models.py
class Document (models.Model):
choice = (('Yes','Yes'), ('No','No'))
authorized = models.CharField (max_length=3, choices=choice, default='No')
Now, as a normal user creates a Document object, the authorized field is no. However, the superior needs to authorize the same before it is actually approved. Now, is there a permission system in django where one user can create an object but not authorize, whereas some other user - who has the permission - can authorize? If not, is the only way to do it is to create a custom field in user model and check it every time?
First of all, why you need to store possible values in CharField and not in BooleanField? I think you should consider changing to BooleanField.
You can do that by providing custom ModelAmin class in admin.py:
from django.contrib import admin
from .models import Document
#admin.register(Document)
class DocumentModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if not request.user.is_superuser:
self.exclude = ['authorized']
return super(DocumentModelAdmin, self).get_form(request, obj, **kwargs)
So now on admin page of Document if it is not a superuser, user won't see authorized field. You can change that code for checking if it should be specific user, or has some permissions, or if user belongs to some Group and etc.
UPDATE
If you want it to be in general views, you can just pass different forms to users, depend on their roles|permissions|groups(i don't know how your so called senior is different from rest of the users). So the answer would be: create two forms, then pass on of them in template based on your request.user attributes.
Django has awesome auth system. I couldn't understand you scenario.
But you could try something like this below
By default every Model object comes with three Permission object like (add_document, change_document and delete_document in your case).
If you want some custom permission you can add it in model Meta class like this:
You can add these permission to User object or Group object.
models.py
class Document (models.Model):
######
class Meta:
permissions = (("Can see document dashbaord", "see_document" ),)
and run python manage.py migrate to create new Permission object with codename as "see_document".
You can implement permissions in request handled by view like this:
view.py
from django.contrib.auth.mixins import PermissionRequiredMixin, permission_required
# For function based view
#pemission_required('document.see_document')
def someview(request):
######
pass
# For class based views
class SomeView(PermissionRequiredMixin, BaseView):
permission_required = 'document.see_document'
This could redirect any user with out the permssion to permission denied page. For more go through this https://docs.djangoproject.com/en/1.10/topics/auth/

Creating custom users in Django and customizing the admin

I need to create custom users in my app.
In the example given in the doc
class CustomUser(models.Model):
user = models.OneToOneField(User)
#custom fields
a user must exists before creating a CustomUser.
What I want to do is to create automatically a User when I create a CustomUser.
In the CustomUser admin (only visible by the superuser), I'd like to have only the custom fields and a few fields from the User model, as well as some form to allow the superuser to change the password for existing instance.
Anybody could help?
The first part of your question is easy, you can use a signal:
def create_custom_user(sender, instance, created, **kwargs):
if created:
custom_user, created = CustomUser.objects.get_or_create(user=instance)
post_save.connect(create_custom_user, sender=User)
As for the second part, theres already a change password form in the admin. To filter out the displayed fields you can create a CustomUserAdmin and register it together with the model. It's pretty self explaining in the django docs.
django docs: list_display

Django admin site: How does the Add User page work (more fields on edit)?

I was wondering how they made it possible to display more fields in the User page of the Django admin site.
If you create a new User you only have some basic fields to fill in, but if you reopen that user (edit mode) then you see a lot more fields to fill in.
I'm trying to achieve the same, I had a look at the add_form.html template but I can't really get my head around it. I guess I'm looking for a way of specifying different fields = [] sets based on the edit status of the document.
Thanks!
The answer lies in the custom admin class registered for the User model. It overrides a couple of methods on ModelAdmin and checks to see whether the current request is creating a new User (in which case the bare-bones form class for adding accounts is used) or editing an existing one (in which case a full form is shown).
Here's my try. When I try to create a new item (Add) it shows only certain fields but then when I hit save it returns an error:
DoesNotExist
in /Library/Python/2.6/site-packages/django/db/models/fields/related.py in get, line 288
admin.py
from django.contrib import admin
from myapp.catalog.models import Model
from myapp.catalog.forms import ProductAdminForm, ProductAddForm
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
#...
add_form = ProductAddForm
def get_form(self, request, obj=None, **kwargs):
defaults = {}
if obj is None:
defaults.update({
'form': self.add_form,
})
defaults.update(kwargs)
return super(ProductAdmin, self).get_form(request, obj, **defaults)
forms.py
from myapp.catalog.models import Product
class ProductAdminForm(forms.ModelForm):
class Meta:
model = Product
#...
class ProductAddForm(forms.ModelForm):
class Meta:
model = Product
fields = ("model", "colour",)