简体   繁体   中英

Django: How to call the same model class inside it s self?

I have a function make_fields_permissions that I need to use it inside the model calss in order to parse the fields and to make permissions for each field like [('can_view_first_name_field','can view first name'),...]

  • goal I need to call and override Person class and inside it self
  • I tried

def __init__(self,*args, **kwargs):
    self.Meta.permissions = make_fields_permissions(self.model)
    super().__init__(*args, **kwargs)

  • My code look like this
from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

    def __init__(self, *args, **kwargs):
        # kwargs['user']['permissions'] =  make_fields_permissions(Profile)
        # x = self['age']
        super().__init__(*args, **kwargs)


    class Meta:
        permissions = make_fields_permissions(Person) #< I can't use the same model inside meta

Your goal is as follows:

  • Goal X (Real goal): Create permissions dynamically according to the model fields
  • Goal Y (Perceived goal that will achieve X): Call the model class while creating it.

Note : See What is the XY problem?

Let us first discuss Goal Y and why it is too complex, and somewhat unfeasable. When one wants to customize how the creation of a class occurs one would use metaclasses , and at first sight this would appear as a perfect solution for your needs (in fact if you do create one properly it would be). But the problem here is that Model already has a metaclass being ModelBase and it is already doing lots of stuff and is a little complicated. If we would want a custom metaclass we would need to inherit from it and very carefully work around its implementation to do what we want. Furthermore making it would not be the end of the story, because then we would need to maintain it since it would be easily breakable by updates to Django. Hence Goal Y is not feasible.

Moving on to the actual Goal X to do that one can Programmatically create permissions [Django docs] . A good place to do this would be in the app configs ready method. For all apps created using startapp there is an apps.py file which has an appconfig inheriting from AppConfig , when the models are loaded its ready method is called. Hence this method is used to do various tasks like attaching signals, various setup like tasks, etc. Modify the appconfig of your app to create permissions programmatically like so:

from django.apps import AppConfig


class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.AutoField' # Don't modify, keep it as it is in your code
    name = 'your_app' # Don't modify, keep it as it is in your code
    
    def ready(self):
        from django.contrib.auth.models import Permission
        from django.contrib.contenttypes.models import ContentType
        from path.to import make_fields_permissions
        from .models import Person
        # import models here, not outside as models may not be loaded yet
        content_type = ContentType.objects.get_for_model(Person)
        for codename, name in make_fields_permissions(Person):
            Permission.objects.get_or_create(
                codename=codename, # 'can_view_first_name_field'
                name=name, # 'can view first name'
                content_type=content_type,
            )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM