How to move models to another section in the Django admin site?
In my application module models.py, I have models that are displaying in admin tool in section called "Backend". I want them to display in another section under the name "Requests".
I tried the following
class TransportationRequest(models.Model):
...
class Meta:
app_label = _('Requests')
db_table = 'backend_transportationrequest'
It is works, but now I have issues with South as it is creating migrations to delete all of these models.
Your current issue is that you are trying to change the app_label and db_table, which ends up changing the location of the model data within the database. By default, the database table is generated as [app_label]_[model_name] (backend_transportationrequest in your case), so when you modify both of these, South detects that the model has been removed and created again, even if this isn't actually the case.
The Django migrations framework introduced in 1.7 should have fixed this, so it detects that the model was moved (instead of deleted and created). You may need to fake a migration along the same lines as this with south, which can be done by modifying the two mgirations it generates to not actually delete and create the tables, but rename them.
Django does not currently allow you to easily do this, as the admin site expects that each application that is registered has a unique app_label. You may have luck playing with the label property of your AppConfig, but this is specifically not recommended and has been historically known to cause massive headaches.
One possibility may be to create a clone of your previous model, and only use it to register the app with the Django admin. You would need to create a proxy model with the custom app_label and db_table. If this didn't work (though it should), the other option would be to clone the model as a unmanaged model using the app_label and db_table.
Related
I am starting with Django App schema design and my schema has UserProfile, UserFavourites and UserComments models .
After doing a bit research i found out that we can user django's own User model or we can create own user model which will extend from AbstractUser
Platform = Django 1.8.5
I have found many similar questions but now that i have newest version of Django framework has anything changed ?
Also need to know pros and cons of each approach
In a new project, strongly consider starting out with a custom User model.
The reason is that if you want to change your User model later, then there is a clear way to do that (migrations). However, switching from a auth-User to a custom User when you already have ForeignKey relations (etc) to the auth-User is a major pain (see below). Considering that it is very easy to just start out with your own model at the start of a project (maybe just copy the auth model), there is very little reason not to.
The docs say this about how hard it is to change AUTH_USER_MODEL later:
Warning
Changing AUTH_USER_MODEL has a big effect on your database structure.
It changes the tables that are available, and it will affect the
construction of foreign keys and many-to-many relationships. If you
intend to set AUTH_USER_MODEL, you should set it before creating any
migrations or running manage.py migrate for the first time.
Changing this setting after you have tables created is not supported
by makemigrations and will result in you having to manually fix your
schema, port your data from the old user table, and possibly manually
reapply some migrations.
Warning
Due to limitations of Django’s dynamic dependency feature for
swappable models, you must ensure that the model referenced by
AUTH_USER_MODEL is created in the first migration of its app (usually
called 0001_initial); otherwise, you will have dependency issues.
In addition, you may run into a CircularDependencyError when running
your migrations as Django won’t be able to automatically break the
dependency loop due to the dynamic dependency. If you see this error,
you should break the loop by moving the models depended on by your
User model into a second migration (you can try making two normal
models that have a ForeignKey to each other and seeing how
makemigrations resolves that circular dependency if you want to see
how it’s usually done)
In other words, if you choose not to use AUTH_USER_MODEL at the start of your project, it's almost impossible to change later.
There is a ticket #24370 for adding custom user model and AUTH_USER_MODEL setting to the default project template, and to recommend doing this in the documentation. This ticket is just waiting for someone to implement it.
Pulled from Django's documentation
If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user
So just add your extra user fields to UserProfile Model. Make a one-to-one relationship with each of your desired model
I am trying to add two additional profile fields and have the native authentication work like normal.
I am trying to fallow the documentation here
and the SO here
In my settings file
#settings.py
AUTH_USER_MODEL = 'users.User'
in my users.user model
#users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
foo = models.CharField(max_length=32, default='Blue')
bar = models.CharField(max_length=32, default='Blue')
print "user.user"
i have created 3 superusers non can log into admin. i have tried syncing the DB after adding a user. i have tried restating the dev server between adding a user.
the only time i see the output of print "user.user" is when i run the createsuperuser command.
i think i cant log in because the user is not really being created. it runs my User class and then skips actually creating the user. but i am kinda new to this so i could be way off and way out of my league.
why cant i log in and how do i add the two fields?
Have you read the warning in Django's documentation?
Changing AUTH_USER_MODEL has a big effect on your database structure. It changes the tables that are available, and it will affect the construction of foreign keys and many-to-many relationships. If you intend to set AUTH_USER_MODEL, you should set it before running manage.py syncdb for the first time.
If you have an existing project and you want to migrate to using a custom User model, you may need to look into using a migration tool like South to ease the transition.
Given this warning, are you working on a fresh database, or are you migrating using South? If you have an existing database and made these changes, then simply running syncdb will most likely no be sufficient.
If this is a development server without any important data, I would recreate your database, and then run ./manage.py syncdb. If you are using a SQLite database, then you can simply copy it to somewhere else (if you would like to keep the data), and run syncdb again to create a new database.
Here is the relevant documentation.
It would also be helpful to know exactly what error you are receiving. Do you attempt to login and admin tells you that your user/pass combination is not correct, or is there an actual error thrown? Your question doesn't quite make this clear.
First, I want to inform that I did check other related questions but their solutions were very simple (improper registration, settings, etc.). This problem is weird in a way that I haven't faced in 3+ years of developing with Django. So here comes:
I have an app that's 90% celery tasks, so it only has two models. They are simple. I have two ModelAdmin classes defined in the admin.py of the app, one for each model. These are simple as well. They are both registered properly. The app is in the INSTALLED_APPS.
All kosher and without any customization of templates, tags or forms, just a plain admin.py:
from myapp.models import (Something, OtherModel)
class SomethingAdmin(admin.ModelAdmin):
# admin config ...
class OtherModelAdmin(admin.ModelAdmin):
pass # Trying anything at this point...
admin.site.register(Something, SomethingAdmin)
admin.site.register(OtherModel, OtherModelAdmin)
So simple it cannot fail, but it does: one of them doesn't show up in the admin. It's simply not registered (404 on manual url access). The other one does show up, and does work properly.
Validation on that invisible admin works because when I add a strange value to its list_display, Django does raise the proper exception (ImproperlyConfigured). So it does reads it, it just fails to register it. If I comment the visible one out, the app is simply removed from the admin (of course, it thinks no modeladmins).
So, in short, one of the ModelAdmins is invisible, while the other one in the same file and with nearly identical configuration, isn't. Any thoughts?
EDIT: Answers to a few suggestions I expect: Yes, the model is working properly (and heavily unit tested), and I have created/saved instances and they are in the db. Yes, I did restart the server. Yes, the computer is plugged in and it's currently on. :)
As it turns out, the problem was in the structure: models was a package, instead of the more usual module. It seems that even if you make the model available at package level (import it in init.py), Django still doesn't know in what app it should be included.
What you need to do is specify the app_label in its Meta class. So the model now becomes:
from django.db import models
class OtherModel(models.Model):
class Meta:
app_label = 'someapp'
# other meta attrs
# Model attrs ...
Odd that it needs to be specified, when the model is available in the usual models.SomeModel namespace, but at least the solution's simple enough.
BTW, as you can guess the other model did include this Meta attr, I just didn't notice it before. LOL.
With Django 1.5 and the introduction of custom user models the AUTH_PROFILE_MODULE became deprecated. In my existing Django application I use the User model and I also have a Profile model with a foreign key to the User and store other stuff about the user in the profile. Currently using AUTH_PROFILE_MODULE and this is set to 'app.profile'.
So obviously, my code tends to do lots of user.get_profile() and this now needs to go away.
Now, I could create a new custom user model (by just having my profile model extend User) but then in all other places where I currently have a foreign key to a user will need to be changed also... so this would be a large migration in my live service.
Is there any way - and with no model migration - and only by creating/overriding the get_profile() function with something like my_user.userprofile_set.all()[0]) somewhere?
Anyone out there that has gone down this path and can share ideas or experiences?
If I where to do this service again now - would obviously not go this way but with a semi-large live production system I am open for short-cuts :-)
Using a profile model with a relation to the built-in User is still a totally legitimate construct for storing additional user information (and recommended in many cases). The AUTH_PROFILE_MODULE and get_profile() stuff that is now deprecated just ended up being unnecessary, given that built-in Django 1-to-1 syntax works cleanly and elegantly here.
The transition from the old usage is actually easy if you're already using a OneToOneField to User on your profile model, which is how the profile module was recommended to be set up before get_profile was deprecated.
class UserProfile(models.Model):
user = OneToOneField(User, related_name="profile")
# add profile fields here, e.g.,
nickname = CharField(...)
# usage: no get_profile() needed. Just standard 1-to-1 reverse syntax!
nickname = request.user.profile.nickname
See here if you're not familiar with the syntactic magic for OneToOneField's that makes this possible. It ends up being a simple search and replace of get_profile() for profile or whatever your related_name is (auto related name in the above case would be user_profile). Standard django reverse 1-1 syntax is actually nicer than get_profile()!
Change a ForeignKey to a OneToOneField
However, I realize this doesn't answer your question entirely. You indicate that you used a ForeignKey to User in your profile module rather than a OneToOne, which is fine, but the syntax isn't as simple if you leave it as a ForeignKey, as you note in your follow up comment.
Assuming you were using your ForeignKey in practice as an unique foreign key (essentially a 1-to-1), given that in the DB a OneToOneField is just a ForeignKey field with a unique=True constraint, you should be able to change the ForeignKey field to a OneToOneField in your code without actually having to make a significant database migration or incurring any data loss.
Dealing with South migration
If you're using South for migrations, the code change from the previous section may confuse South into deleting the old field and creating a new one if you do a schemamigration --auto, so you may need to manually edit the migration to do things right. One approach would be to create the schemamigration and then blank out the forwards and backwards methods so it doesn't actually try to do anything, but so it still freezes the model properly as a OneToOneField going forward. Then, if you want to do things perfectly, you should add the unique constraint to the corresponding database foreign key column as well. You can either do this manually with SQL, or via South (by either editing the migration methods manually, or by setting unique=True on the ForeignKey and creating a first South migration before you switch it to a OneToOneField and do a second migration and blank out the forwards/backwards methods).
The import statement import the needed parts. but is the "user" class already made when you put that into your installed apps? or do you still need to clarify in models.py in order to make the table in the db? or can someone expand on how to use django users and sessions? I'm looking over the django docs right now and they all just go over how to use the thing once. they never put the code in a syntax where users are going to be the ones using the code through a browser and not you through a python shell.
All installed apps can contribute to the database schema. django.contrib.auth.models contributes, among others, the auth_user table behind the django.contrib.auth.models.User model, therefore you do not have to worry about recreating it unless you have a specific reason to do so.
There's a number of things going on here. As you're aware, Django comes with a number of "contrib" packages that can be used in your app. You "activate" these by putting them into your INSTALLED_APPS.
When you run python manage.py syncdb, Django parse the models.py files of every app in INSTALLED_APPS and creates the associated tables in your database. So, once you have added django.contrib.auth to your INSTALLED_APPS and ran syncdb, the tables for User and Group are there and ready to be used.
Now, if you want to use these models in your other apps, you can import them, as you mention, with something like from django.contrib.auth.models import User. You can then do something like create a ForeignKey, OneToOneField or ManyToManyField on one of your models to the User model. When you do this, no tables are created (with the exception of ManyToManyField; more on that in a bit). The same table is always used for User, just as for any of your own models that you might create relationships between.
ManyToManyFields are slightly different in that an intermediary table is created (often called a "join table") that links both sides of the relationship together. However, this is purely for the purposes of that one particular relationship -- nothing about the actual User table is different or changed in any way.
The point is that one table is created for User and this same table is used to store all Users no matter what context they were created in. You can import User into any and all of your apps, create as many and as varied relationships as you like and nothing really changes as far as User is concerned.
If the table name or something else does not fit in your needs you can always just extend the User model.
from django.contrib.auth.models import User
class Employee(User):
...
Any class extending Model class in models.py contributes to database schema. That means, django search your (and also django core) model.py files and looks for any class that extends Model like:
some models.py
class SomeModel(Model):
...
...
class Otherthing(Model):
...
that is also applies for django core code files. Since all Database tables named using application label and model name, database ables created by django also have that...
For example,
from django.contrib.auth.models import User
If you track file hierarchy django -> contrib -> auth and open models.py file, you will see related model. Ther are also other Model classes in here, like Permission and Group models.
Since these models are under auth application, database tables are auth_user, auth_perission and auth_group
When you run manage.py syncdb command for the first time, django will create these tables...