Custom model permission in django-admin to edit a particular field - python

Normally, after migrating the models located in models.py, in django-admin you get a set of default permissions for your models. For example:
models.py
class Appointment(models.Model):
time = models.TimeField(auto_now_add=False, auto_now=False, null=True, blank=True)
notes = models.TextField(blank=True, null=True)
In django-admin I can assign these permissions to a group:
appname|appointment|Can add appointment
appname|appointment|Can change appointment
appname|appointment|Can delete appointment
appname|appointment|Can view appointment
However, I want to add a new permission to this list that will be able to allow a staff user to change the notes field only, such as:
appname|appointment|Can change appointment notes
I know I can add it like this:
class Meta:
permissions = [
("change_notes", "Can change appointment notes"),
]
However, the lines above will only add the permission to the list, and after assigning it to a group nothing happens (the notes field cannot be changed).
How can I solve this? Is there any Django extension that can help me add a custom model permission in to edit a particular field?

Related

Custom django permissions for group chats?

I have a custom group model like this:
class MyGroup(models.Model):
name = models.CharField(max_length=200,null=True,blank=False,default="Group name")
members = models.ManyToManyField(get_user_model(), blank=True, related_name="grpmembers")
created_by = models.ForeignKey(get_user_model(), on_delete=models.DO_NOTHING, null=True, blank=False, related_name="createdby+")
created_at = models.DateTimeField(editable=False)
It works, it's fine, I override the save method in django admin so the created_by will point to the logged in user on save.
Problem #1
Even if you are the creator of the group, you can select yourself to either be in- or be removed from the group which kinda looks silly. I'm thinking of solving this by saying the user can view the group if they're in members or created_by.
Problem #2
Custom permission. I want to have some permissions, like:
Can view the group: which means the user is either the creator or is in the members list
Can edit the group: which means the user is the creator(can edit their own) or is staff(can edit anyone's stuff) or is superuser(root)
I can write it down and imagine how it would work, but I have no idea how to implement these.
I've found some ways, like creating a Meta and defining permissions there and also making the permissions as def(/functions), but how could I access the currently logged in user?
Like okay let's say I do
def can_view_group(self):
r1 = self.filter(members=req.user) # where req.uset is not accessible bc we're in models.py
, but how do I tell the permission to check the currently logged in user?
The problem is doing all the logic in models.
Over problem 1 you need to verify user is not owner before allow to leave in the views.py.
Over the problem 2 are 2 solutions, or you move can_view_group to views.py, or you define that in models as:
def can_view_group(self, user):
#all the logic
And you pass the user from views.py

Delete 2 model different objects which reference each other as foreign keys

We have two Django models:
class Project(models.Model):
project_title = models.CharField(max_length=30)
owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
class User(models.Model):
usernmae = models.CharField(max_length=50)
active_project = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING, related_name='current_project')
I have a user with object (with id say 692). And this user created a project with id=12345, therefore these owner field will get have this particular referenced.
I want to delete that user. But it shows error that
delete on table "app_user" violates foreign key constraint
This is expected as on_delete=models.DO_NOTHING, was set. One way I found out was using on_delete=models.CASCADE.
Question: How should I go about deleting the user (692) without changing the model definition(having to re-run migration)?
Doing it manually by deleting the project first, leads to the same foreign-key error, as owner field is User object.
How to handle this mutual foreign key relationship while deleting, as deleting any one of those two throws the foreign-key exception?
Update
Some correction in the model definition username is the field name instead of usernmae (typo). And the foreignkey for project is Project not the User model.
class Project(models.Model):
project_title = models.CharField(max_length=30)
owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
class User(models.Model):
username = models.CharField(max_length=50)
active_project = models.ForeignKey(Project, null=True, on_delete=models.DO_NOTHING, related_name='current_project')
IF you really don't want to make a migration (any specific reason?) and if you are ok with doing this manually this time. Then you have two options:
Go into the admin panel and manually change the User field in the project instance to a different user or to NULL. Now you should be able to delete the User instance since it's not referred anymore into the project.
If that worked, you can then delete the project instane as well.
Curios if this will work, let me know!

User with permission to modify only one field of the model in the Django Admin

I have a user named ExpertUser who should only be able to modify an attribute of the called model (money) of the users in the Django Admin.
I have tried adding permissions in the model using the Meta but when entering with that permission I can not modify anything since I do not have access to any user.
My model is this:
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
money = models.FloatField(default=1000)
def __str__(self):
return self.user.username
class Meta:
permissions = (("can_view_money", "Can view money"),)
Have a look at Django Guardian. That provides more flexibility in assigning permissions on various levels. Django only lets you set permissions at object level, so in your case you were only able to set permission to create/edit/delete Client objects.
http://django-guardian.readthedocs.io/en/v1.4.8/index.html
If that doesn't suffice, there are a few other packages with the desired functionality:
https://djangopackages.org/grids/g/perms/

Django - Some Models are not Editable/Createable in Django-Admin

I have 5 models in one of my apps
Report ReportData Customer ..etc
For some reason, ever since my last deployment, I can no longer change or create new Report or Customer objects, but everything else works? Any idea why this would be happening? The admin page just outputs nothing on the add link and the change link outputs nothing as well.
Django==1.9.1
I have tried restarting servers, running migrations, and restarting database. The development version works fine. Such a strange problem.
As you can see, there are no fields even though this object has been populated with tons of data in the database.
Here is my Report model:
class Report(models.Model):
public_uuid = models.UUIDField(max_length=256,default=util.make_uuid,unique=True)
customer = models.ForeignKey('Customer')
has_payed = models.BooleanField(default=False)
#... etc
Here is how I register items in the admin:
admin.site.register(Customer)
admin.site.register(Report)
admin.site.register(...etc)
The other 3 models I have work fine. The only difference between these two models and the other three (that work and are editable with the admin tool) is that these two models have #property and #staticmethod methods attached to them.
Just had this issue
When using auto_now_add=True or editable=False in the field definition, the admin will not show the corresponding fields unless you specify them in the readonly_fields of the admin form definition.
if in models.py
class TransmissionLog(models.Model):
dataSource = models.ForeignKey(Browser, editable=False)
dateCreated = models.DateTimeField(auto_now_add=True, editable=False)
then admin.py needs
class TransmissionAdminManager(admin.ModelAdmin):
readonly_fields = ['dataSource', 'dateCreated']
admin.site.register(TransmissionLog, TransmissionAdminManager)

Django migration error involving m2m field

I am trying to modify my creator field from a ForeignKey to a ManyToManyField in hope of being able to select many users to be the creator.
When I make the change in my code, I receive the following error when making the migration:
"You cannot alter to or from M2M fields, or add or remove through= on M2M fields."
Would anyone know how to make this change possible for the migration to be successful?
Please see my code below.
Thanks in advance!
class Event(models.Model):
title = models.CharField(_("Name of client"), max_length=100)
creator = models.ForeignKey(settings.AUTH_USER_MODEL, null=False, blank=False, verbose_name=_("client"),
related_name='creator')
start = models.DateTimeField(_("start"))
end = models.DateTimeField(_("end"), help_text=_("The end time must be later than the start time."))
calendar = models.ForeignKey(Calendar, null=True, blank=True, verbose_name=_("calendar"))
You must remove your ForeignKey, create and run migrations, and then add your ManyToManyField. Django currently can't do this in a single step.

Categories