Adding permissions to Django model without table - django

I'm working on some Django Rest Framework based project (quite expected API for some web-app). It has as traditional Django models, and some kind of model-like objects: they behave like Django models but don't store anything in DB. No tables, no content-types. When we ask them for objects, they goes to external API and forms resulting Queryset.
Now I need to build some role-based access system. To make the architecture clear and extensible, I want to make groups and permissions managable through the Django Admin interface. So, I guess, we need to put some permissions to DB and then we'll be able to add these permissions to user groups. After that, we'll check these permissions in DRF.permissions class. But since we have neither tables, nor content-types for these 'models', we can't add records to permissions table right now.
What is the right way to make this possible? Should I rebuild these 'models' through the metaclass with proxy = True? Or should I add a proxy layer above? Maybe I should add some dummy content-types by hand?

Related

Django Admin LogEntry: how it works in non admin actions?

I am having some struggles how does exactly django.admin.LogEntry objects are created.
Consider the following scenario:
I have a bunch of functions which take a csv file with data that allow me to create multiple objects at one call (just iterate through the file, use the data and if data in given row is correct: create a Model instance). I want to make sure that that each of that creation will be logged.
The question is: django docs are not very descriptive on how does LogEntry works and I am not sure if such actions (not taken in the admin panel itself) will be logged there. Also: will the LogEntries be created for the related objects or I have to trigger them manually?
Does anybody got any experience with such scenarios and can share thoughts about it?
The LogEntry model is in the Admin package and only used by Django admin by default. It is used in the admin layer and not model layer when saving objects. if you want to use it outside the admin, then you will have to manually create the entries yourself. That also means the admin will likely display entries of changes made by normal users so you have to think about how you want the entries displayed

Django app has multiple database and multiple user

I have written one Django cloud based app. This app will have multiple user and for them multiple database, so that their data should be separate and they can save only to same database.
1) How can we implement it
2) How to automatically one user from login page to assign the database to write on it.
I don't have a complete answer, since you do not give a lot of detail. But here are a couple ots that f hinDjango supports custom database router implementations. A database router is a class that helps django decide which database to use for a particular model. Unfortunately I don't think this mechanism is granular enough for your needs. You can also specify the database to use in your code by using using(name) queryset method and save(using=name) form of save() method for instances. Of course this also means that some features of Django are going to be unvailable to you, since you cannot always expect to have a user. Look at the docs here for more info
https://docs.djangoproject.com/en/dev/topics/db/multi-db/

How to write reusable apps with customizable models in Django?

I want to make reusable apps, that allow for customization by the integrator.
An example is if I make a newsletter signup app with the bare minimum of storing email address, but the integrator later wants to add additional fields, like say a name. What is the things I need to do to allow for this easily?
I went down the path of swapping out the models, like Django's auth system does, but that didn't work well. Then I found swappable attribute in the Meta class and a package that does this, but both are not intended for external use.
The only way I can think of for the integrator to do is, allow them to provide custom forms by passing it into the view in the urls for instance.
url('^someurl/$', MyView.as_view(form_class=SomeForm), name="myurl")
Then have a secondary model, with foreign keys to the internal newsletter model, but this means a secondary table that needs to be joined.
Another alternative is to try Abstract models, but I'm not sure what the impact will be there.
So what is the Django/Pythonic way of solving this?

Disallow linking objects based on a rule

I have two models: Domain and Record. Many records link to a domain. The domains and records have their owners. I want to disallow users to create records in domains that they don't own. However they should be able to edit records if someone else (a superuser e.g.) created them and set owner to that specific user (even if they don't own a domain). This should work both for admin site and for API (rest_framework)
My question is - what is the simplest way to achieve this goal? Is there some django plugin that handles permissions for linking? Can I use model validators here (if so - how to distinguish if a new object is created)?
The problem here is that the Django Rest Framework and Django itself (via admin) are interacting only at the level of the models. In order to achieve your goal I would implement the following design:
Make the models aware of their owners and users. For that I would use django-audit-log.
Overwrite the default model Manager and build your logic in the create method, where I will query the user's attributes and throw appropriate exceptions.
Such a design shifts some of the business logic from the controller to the data model - there are some debates out there about the benefits and pitfalls of such an approach. But with the underlined constraints (Django admin and API) is the only common place where you could put it.
Is this what you are aiming for ?

Can i avoid the creation of the Django auth.model.User table when using "other authentication sources"?

As the Django documentation says about Other authentication sources, in order to authenticate against another source, you must implement your own authentication backend. Also, They explain that:
The Django admin system is tightly coupled to the Django User object described at the beginning of this document. For now, the best way to deal with this is to create a Django User object for each user that exists for your backend (e.g., in your LDAP directory, your external SQL database, etc.)
As i'm not going to use the admin system (i'm assuming they are referencing the admin application) can i avoid that table replication?
I was thinking of implementing the authenticate and get_user methods as the doc says but that implies the instantiation of the User class, so the next question would be: can the auth.models.User class be instantiated without having the actual Django User table?
The short answer to your question is - yes, it can. Simply set the managed property to False on the User model.
You should map the user from the external authentication into the auth.User object.
Remove django.contrib.auth from the INSTALLED_APPS setting.
Is there a particular reason you don't want the table to be created? If you write (or use a pre-existing) LDAP authentication backend, the User objects will be stored in the table, but they won't have any password information stored, and you can easily update fields like email address and name during the authentication process, so you won't create a disconnect between information stored in LDAP and managed in the Django table (i.e., you can continue updating auth information from LDAP, and don't have to worry about also updating it in the Django DB).
There's no way to avoid the table and still have any sort authentication. The "alternative" authentication methods still make use of the auth_user table, they just authenticate via another means.