how to set the default permission name created in Django? - django

I'm using django 1.6
Now when I define a model, it will create three permissions record for it (can_create, can_update, can_delete).
I'm now adding other permissions on the models (which doesn't matter in this question), and want to make a view to let the user assign them all to users and groups.
Now the problem is:
I want to replace the default name displayed for the three default created permissions.
Is there any way to do this?

Yes there is possibility to create custom permission while creating the models/table in django. But this will create the extra custom permission, by default 3 permission will create i.e( add, change, delete). One can create custom permission by following thing.
class Task(models.Model):
...
class Meta:
permissions = (
("view_task", "Can see available tasks"),
("change_task_status", "Can change the status of tasks"),
("close_task", "Can remove a task by setting its status as closed"),
)
The only thing this does is create those extra permissions when you run manage.py migrate (the function that creates permissions is connected to the post_migrate signal). Your code is in charge of checking the value of these permissions when a user is trying to access the functionality provided by the application (viewing tasks, changing the status of tasks, closing tasks.) Continuing the above example, the following checks if a user may view tasks:
user.has_perm('app.view_task')
One can see the django doc here django permission description

Based on this blog post and this Django ticket, I would say it is not possible and also not advisable to change these codenames (since they are used in the admin). It is however possible to change the human readable name (such as 'Can add permission')

I cannot add comment to the answers already there, hence adding a new answer.
I have been looking for a solution and could not find any. So I just make use of default permissions and use permissions to re-create them and use whatever name and codename you want. Django documentation here
class Foo(models.Model):
title = models.CharField(max_length=250)
class Meta:
default_permissions = ()
permissions = (
("add_foo", "Can add foo"),
("change_foo", "Can change foo"),
("delete_foo", "Can delete foo"),
("view_foo", "Can view foo"),
("list_foo", "Can list all foo")
)

Related

Why Django auto adds permissions to group?

Currently I'm making some groups for my backend and I noticed through the admin panel that the groups have some extra permissions I did not add. What is the cause of this behavior?
models.py:
produccion_group, created = Group.objects.get_or_create(name="Produccion y cuentas")
produccion_group.permissions.add(
Permission.objects.get(codename='add_brand'),
Permission.objects.get(codename='change_brand'),
Permission.objects.get(codename='view_brand'),
Permission.objects.get(codename='add_expense'),
Permission.objects.get(codename='change_expense'),
Permission.objects.get(codename='view_expense'),
)
produccion_group.save()
Admin panel:
The problem is solved by adding the following block of code. Still doesn't answer the incognita of why it's added automatically, but fixes the unwanted permissions.
def ready(self):
produccion_group.permissions.remove(
Permission.objects.get(codename='add_user'),
Permission.objects.get(codename='change_user'),
Permission.objects.get(codename='delete_user'),
Permission.objects.get(codename='view_user'),
Permission.objects.get(codename='add_group'),
Permission.objects.get(codename='change_group'),
Permission.objects.get(codename='delete_group'),
Permission.objects.get(codename='view_group'),
)
produccion_group.save()

Request changes/additions to data in another app

To make a long story short, I am very grateful for hints on how I can accomplish the following. I have an app A that I don't want to change. I have an app B that needs to select data from A or to request data to be added/changed if necessary. Think of B as an app to suggest data that should end in A only after review/approval. By itself, B is pretty useless. Furthermore, a significant amount of what B's users will enter needs to be rejected. That's why I want A to be protected so to say.
# in app A
class Some_A_Model(models.Model): #e.g., think artist
some_value = models.TextField()
# in app B
class MyCustomField(models.ForeignKey):
...
class Some_B_Model(models.Model): # e.g., think personal preference
best_A = MyCustomField('Some_A_Model')
worst_A = MyCustomField('Some_A_Model')
how_many_times_I_like_the one_better_than_the_other = models.FloatField()
class Mediator(models.Model):
# already exists: generic foreign key
content_type = models.ForeignKey(
ContentType,
on_delete=models.CASCADE
)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey(
'content_type',
'object_id'
)
#does not yet exist or needs to be changed:
add_or_change = PickledObjectField()
Django should create a form for Some_B_Model where I can select instances of Some_A_Model for best_A and worst_A, respectively; if, however, my intended best_A is not yet in A's database, I want to be able to request this item to be added. And if I find worst_A is present but has a typo, I want to be able to request this item to be corrected. An editor should be required to review/edit the data entered in B and either reject or release all the associated changes to A's database as an atomic transaction. I don't want any garbage in A and refrain from adding some status field to track what is considered valid, requiring filtering all the time. If it's in A, it must be good.
I figured I need to define a MyCustomField, which could be a customized ForeignKey. In addition, I need some intermediate model ('mediator' maybe?) that MyCustomField would actually be pointing to and that can hold a (generic) ForeignKey to the item I selected, and a pickled instance of the item I would like to see added to A's database (e.g., a pickled, unsaved instance of Some_A_model), or both to request a change. Note that I consider using PickledObjectField from 'django-picklefield', but this is not a must.
As there is only some documentation on custom model fields but not on the further steps regarding form fields and widgets, it seems I have to dig through django's source to find out how to tie my intended functionality into its magic. That's where I am hoping for some comments and hints. Does my plan sound reasonable to you? Is this a known pattern, and if so, what is it called? Maybe someone has already done this or there is a plugin I could look into? What alternatives would you consider?
Many thanks in advance!
Best regards

Add password to Django Group model

Is it possible to password protect groups so that a user can only join a group if the user has a password for that group?
I know it's possible to add fields to the Group model with
Group.add_to_class('password', CharField(max_length=180, null=True, blank=True))
But how can I implement this in a secure way? I want the password to be properly hashed and stored. In essence, how can I add the User password field to Group as well?
EDIT:
The docstring for the Group class in the source.
Groups are a generic way of categorizing users to apply permissions,
or some other label, to those users. A user can belong to any number
of groups.
Beyond permissions, groups are a convenient way to categorize users to
apply some label, or extended functionality, to them.
All I'm using a group for here is a label, and I want to password protect that label for when users try to join.
After considering your responses in the comments, I believe your best bet will be to subclass Group and then implement an authentication procedure within it. Then you can use the functions make_password, check_password, and is_password_usable as documented here to manage the authentication process.

How to find user group and use of caching in django?

I am new to django/python and working my way through my webapp. I need assistance in solving one of my problems.
In my app, I am planning to assign each user (from auth_user) to one of the group ( from auth_group). Each group can have multiple users. I have entry in auth_group, auth_user and auth_user_groups. Here is my question:
At time of login I want to check that logging user belongs to which group?
I want to keep that group info in session/cache so all pages I can show information about that group only.
If you have any sample code will be great.
Giving support to the very well #trinchet's answer with an example of context_processor code.
Puts inside your webapp a new file called context_processors.py and writes this lines on it:
def user_groups(request):
"""
Add `groups` var to the context with all the
groups the logged in user has, so you can access
in your templates to this var as: {{ groups }}
"""
groups = None
if request.user.is_authenticated():
groups = user.groups
return {'groups': groups}
Finally on your settings.py add 'webbapp.context_processors.user_groups'to TEMPLATE_CONTEXT_PROCESSOR:
TEMPLATE_CONTEXT_PROCESSORS = (
'webbapp.context_processors.user_groups',
)
1) Be user an instance of auth.models.User, you can get all groups the user belong to, through user.groups. If you want to ask at time of login then you should do this in your login view.
2) You can use session or cache approaches to deal with, this is irrelevant, but once you have the group you need to render the pages having this value, i mean, you need to provide the group to the template rendering, to do this I suggest to you using a custom context processor.

django admin filter tweaking

I want to use django's admin filter on the list page.
The models I have are something like this:
class Location(model):
name = CharField()
class Inquiry(Model):
name = CharFiled()
location = ManyToManyField(Location)
Now I want to filter Inquiries, to display only those that contain relation to specific Location object. If I use
class InqAdmin(ModelAdmin):
list_filter = ['location', ]
admin.site.register(Inquiry, InqAdmin)
the admin page displays me the list of all Locations and allows to filter.
What I would like to get, is to get list of only those locations that have some Inquiries in relation to them (so I don't ever get the empty list result after filtering).
How can this be done?
You could create a custom manager for Locations that only returns Locations that have an Inquiry associated with them. If you make this the default manager, the admin will use it.
Only caveat is that you'll need create another manager that returns all Locations and use that in the rest of your app whenever you want to retrieve Locations that don't have an associated Inquiry.
The managers section in the Django docs is quite good, and should be all you need to get this set up.
EDIT:
sienf brings up a good point. Another way to accomplish this would be to define a subclass of django.contrib.admin.SimpleListFilter, and write the queryset method to filter out Inquiries with empty Locations. See https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter