Django model with dynamic fields based on foreign key - django

I am trying to implement a model where only a subset of the fields should be presented in forms, based on a foreign key in the model.
The total number of fields is relatively low (~20), but may change frequently with different values of the foreign key.
I would like to use something like single table inheritance, but with a single model (no inheritance). I looked at existing packages eav, dynamic models... but they did not seem to fit my needs.
I part of the requirement is that I would like to query the models by sql without too many joins.
Here is a use case representing applications to grants based on a request for application (rfa). The rfa is entered in the admin by staff and the applications are made by end users.
application class
rfa (request for application): foreign key
field_1
...
field_20
rfa class:
app_fields (coma separated list of field names)
In the forms, only the fields in app_fields should be visible for a particular rfa.
I have the rfa part covered with django-separatedvaluesfield and I was wondering how to implement the application pages so that they work with generic views in the frontend and admin, and be DRY.
For the update views, I could have a method in the application model, but it would not work for create as the rfa is not defined for create:
def get_current_app_fields(self):
return self.rfp.app_fields
Any ideas on the best DRY strategy to implement frontend views and admin?
Thanks.

Related

Best approach to enrich User model in Django pluggable app

I am currently working on expanding https://github.com/suutari/drf-jwt-2fa, which provides two-factor authentication over jwt for rest-framework.
I would like to make the two-factor auth non-enforced; that is, users should be able to choose if they want this extra security.
For that purpose, I would like to add a boolean field (lets call it two_auth) to the user model.
What is the best approach to add this field?
I am currently thinking on some possibilities, but none of them seems to be neat enough:
Create a relation table (user_id, two_auth) without foreign-key enforcement: I should use signals for user deletion
Create a relation table (user_id, two_auth) with foreign-key enforcement: The foreign key should point to the model specified at settings.AUTH_USER_MODEL. I generally like model declaration parameters to be explicit, not patchable.
This is a nice guide on options to extend the built-in user model.

How do we change Field Names in our existing Users table in django

I am trying to Edit Users Table in Django. I am using Users Table to login or register a users. I have to add a new field name Role in that Table but i can't find any option to edit that existing table in admin section.
i just try to field some files to field out where the code of that existing Table is but did't get it.
is there any way to Edit the Table or I have to Create a New Table and have to create a new method of registration.
i am not expert so it's hard to me understand things.
Well first, the Django admin interface it's just for performing CRUD operations over already existing models, you are not able to change in any way the database tables (at lest not using the "out of the box features") using the admin interface.
Said that in order to do what you want to do, with any model (not just User), you should:
Add the field to the model.
Instruct the admin interface to list this fields along the others.
Now the user model is kind of a special model here so I'll recommend a couple of readings you should complete before go forward with the model User customization.
References (User customization): Substituting a custom User model, Extending the User model.
And for the admin interface ...
Reference (admin interface): ModelAdmin options, special attention here to list_display

How to dynamically swap default database on the model manager in django?

I am creating a project in django and django rest framework. Its an api for an angular app. The database setup consists of multiple databases. one is default database, all the django tables reside in this database; rest of the databases belong to a type of a user, each user is supposed to have a separate database. So, all the user related data goes to its separate database. To implement the selecting database dynamically, user object has an extra field to store the database to write to.
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
"""Custom User model."""
database= models.CharField(max_length=9)
Reason for doing this was performance improvement as each database is separate, ListView and DetailView would work faster than if the data was stored in the one database only.
I know I can choose a database to store by using the using method on the model manager. In the rest api things work fine and data is being stored in their separate databases, but I end up overriding methods that django has defined. Its adding development cost to the project. Foreign keys and ManytoMany keys needs to be resolved with the current database of the user, which is not happening as I have customized the database setup. Also, my code cant be as good as theirs :p , as they have written django over the course of many years.
I have overwritten many querysets already, but django still uses default database many times. If only I could use the request object in the model manager of django models to swap the default database on per request basis, things would be different i think.
My questions are -
Is there a way to access the request object in the model manager? I could do something to the effect of below code.
class CustomManager(models.Manager):
def get_queryset(self, request):
return super(CustomManager, self).using(request.user.database).get_queryset()
Model manager has _db property that could be used to select database. Would overriding it is advised? if yes, how and where in the code?
Is there a better way to implement the separate databases?
Thanks in advance.
Regards
Using a database router is recommended in Django docs, but the problem is it only accesses the model class.
Found a couple of questions related to the problem of switching databases dynamically. This post has a solution that would solve the problem of passing the request.user or any other parameter by using a threading.local instance.
Someone created a reusable plugin even for this - https://github.com/ambitioninc/django-dynamic-db-router
Hope that helps.

Django foreign key constraint with Model that lives in different database

I'm trying to use the oauth2_provider library which provides a model for AccessToken, which foreign keys into a User model. My User model will actually live in a different database from the OAuth2 token models. I can use a router to direct which DB to use for a particular model, but am I correct in concluding that Django would not support a foreign key to a model in a different DB?
If I still wanted to extend from the AbstractAccessToken with my User in a different DB, is there any way that Django allows me to populate the user_id foreign key column at all? Or would I simply need to leave it null and define and have my custom AccessToken class define its own unconstrained external_user_id column?
Django doesn't support any ForeignKey operations that span multiple databases. So, as you suggested, I think the best you can do is to provide your own IntegerField for the user and use it manually. Unfortunately that may require a lot of fiddling with that third-party library if it has a lot of internal code that's expecting to pull the user from the database.

Django add a many to one field to user object

I'm creating a Network class that has a many-to-one relationship with the Django User class. In other words, a Network can have many User and each User has only one Network. It's easy to add many-to-many relationships because I can add the many-to-many field in the Network class; however, it's hard to apply many-to-one relationship since I need to add the the foreign key in User class. There is no way I can do that.
I do have a UserProfile class that has a one-to-one relationship with User, but it's only for storing additional information about the User, not any relationships. All my other relationships defined are relating to User, not UserProfile.
Is there a way to create a many-to-one relationship to the User and Network class without using the UserProfile? Thanks!
The only things I can think of are subclassing User, which is tricky because the admin has no way to turn a base object (User in this case) into a subclassed object (NetworkUser, and yes I've tried), or creating a NetworkUser model with a OneToOne relationship to User and a ForeignKey to Network. I'd recommend the latter, because while you feel sure now that you just want to add one thing to User and it shouldn't be a big deal, later on there will be more to add.
The thing that bothers me about directly messing with User is that this is only for a single app, not necessarily the whole project, and modifying User in a way that will affect other apps in the project.