How to retrieve data from DB without rerunning the server? (Django) - django

so I have multiple apps for my website; one to register, one to view a map with the users locations plotted on, and one to view the users' profiles. But those three apps need access to the same model, namely: User. (On the register page it gets created and added to DB, the map page needs its hometown in order to locate it on the map, and the profile pages also need it obviously). But whenever I add a new user on the admin page, I first have to rerun the server in order for it to appear on the map. Beforehand when the model was defined in just one app, I just needed to refresh the page to see the change. I have created the User model in the Register app and redirected to it in other apps like this:
class Meta(models.Model):
db_table = 'register_User'
Why doesnt the template retrieve the up to date data without restarting the server?
I hope u can help out

The way you are using the Django ORM is not correct.
You should not use the Meta in a models.Model class to reference a table in order to be able to access it.
If you need a model from a different app, just import it like this:
from user.models import User
And then you can use it in your views or models.
For a better understanding on how the Django ORM works, i recommend the Django tutorial or the models.Model reference pages.

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

Registering a dummy model in Django admin to control multiple models data

Is it possible to register a dummy model (Does not exist in db) that will display data from multiple models in one page?
Maybe just list all objects and when use click on one, a new webpage is opened with details of the clicked on objects? Which is usually this view:
admin:{app_name}/{model_name}/{object_id}/change
The closest standard solution to what you want are Django inlines:
https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#using-generic-relations-as-an-inline
I fail to see how you could create a model not present in the db.

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.

Adding fields to user's personal info in Django admin page

I just started a Django project (there are no apps in it). I activated the admin in settings file and can access the Django administration page. There is a column in Django page to add users; while adding users I get only three fields under personnal info, but I need to store some more information about users. I Googled around and found that I can use user profiles to accomplish this. I tried, but I am having problems.
My aim is to add three more fields to the user table:
role
contact number
other
I need details like: which function I need to write and where to do this.
I found this, but I do not know where I need to write these steps. I would greatly appreciate a more clear explanation of this.
Django User Profiles is what you need. The blog you linked to has clear steps on how to do it. You can check out the Django documentation. http://www.turnkeylinux.org/blog/django-profile also provides a good explanation.
Basically you need to create a new model with User as ForeignKey and define the model in the settings.py as AUTH_PROFILE_MODULE = "django_app.your_profile_modelname". Create the profile and save it just like any other model, and access it using user.get_profile()
Adding a couple of things in response to your questions below:
First, do not create apps as a directory. Use startapp <appname> [destination] as described here. That will create the app directory.
Second, you have to add the app to INSTALLED_APPS in the project's settings file, do a syncdb. Basically, follow the steps in Django tutorial on writing your first app.
Third, UserProfile is a separate model. It is not an extension of User. It is associated with the User just because you added User as the ForeignKey.
Fourth, to be able to see the user profile model in admin, you do exactly what you would do to add any other model to admin page. Create a file names admin.py under your app with:
from django.contrib import admin
from myproject.app.models import UserProfile
admin.site.register(UserProfile)
There are three key concepts to understand:
There is no built in "profile" system in Django, beyond the limited auth app which is really geared just to user login. You are expected to roll your own.
There is nothing magical about a profile record in itslef, it is just like any other record that takes User as a foreign key (or, more properly, a one-to-one field as per the docs). You create it by creating a custom django app (traditionally called profiles) and a model for that app (traditionally called UserProfile, since Profile is not allowed as a model name).
The only thing that sets UserProfile aparts as a model is that you specify it as the AUTH_PROFILE_MODULE which means that it is accessible when called .get_profile() on a User record. That's it. If you set up the UserProfile like so:
def UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
other fields
then you can also access the profile as user.profile rather than user.get_profile() which some people prefer.
Again, nothing magical about the profile model -- it is just a model record like any other model record.
If you want to be able to edit additional fields within the user form that's more complicated; easiest way is probable unregister User and then register it again using your custom ModelAdmin and form class but judging by your question you're probably not at that level yet.

django: Hide Model Types with no instances on Admin page

Say I have an app with ModelA, ModelB, and ModelC
For my app's admin page (/admin/app), how do I hook into the display of the "App administration" page so I may hide Model types that are empty (have no instances)?
That's a big ask, because you'd have to dynamically register/unregister apps according to the results of a database/ORM query (a count(), at least) for each of the models that each of the INSTALLED_APPS contains.
Every single time you viewed the admin.
While that in itself is unpleasant enough, bear in mind that admin.py for each app is processed at server restart/reload time (IIRC), so you could't hope to hook up something cute like those DB lookups there, as it'd only get run once and not reflect the actual state of models currently have objects stored in your database.
Better move: leave it be. If there are no objects to view for a given model, then there are no objects to view for a given model.
If you're concerned about your client/user making new models in there when they shouldn't, then that's a combination of user education and admin user permissions that you can sort out.
As said in a few places: "The Admin is not your app." If the customization goes beyond the trivial, it's time to write your own views. You can still hook them in to the admin site by overriding the base admin template and even serving them from the same root path as the rest of your admin.