Migrate user groups and permissions in Django? - django

I've built an application that I want to move from my development server to my production server. In this application I have defined 3 custom groups in auth.group and each of those have specific permissions.
I've tried to dump the data from auth.group - it seems to include permissions ids as well. The problem is, those IDs don't match between my development environment and the production environment. It also seems there is a content_type_id in auth.permission that I don't know how it relates.
My question is, is there a way using dumpdata or something else, to migrate Groups and all of the related permissions for my application? I don't have a problem importing multiple fixtures on the production server, but I do want all of the groups to be set up without having to go through the UI and selecting the appropriate permissions for each group.

django.contrib.auth depends on django.contrib.contenttypes because auth.models.Permission.content_type is a ForeignKey(ContentType).
Solution: add ContentType in your data dump, ie. dumpdata with the following arguments: auth.group contenttypes.contenttype auth.permission

Related

Detect database DDL schema changes with Django

Let's say that we have a Django app that looks on a legacy database.
If someone make changes on some database tables from a db client as DBeaver for example and not through Django models, is there a way to identify these changes?
You can do in a terminal, inside your Django project directory : python manage.py inspectdb > models.py
You will have models related to your tables.
By default, inspectdb creates unmanaged models. That is, managed = False in the model’s Meta class tells Django not to manage each table’s creation, modification, and deletion.
If you do want to allow Django to manage the table’s lifecycle, you’ll need to change the managed option above to True (or remove it because True is its default value).

What is the best way to prepopulate Groups table and permissions for it at application startup?

My goal is:
to have created custom Groups and populated with permissions for specific models. All that immediately after or during application starts
Question:
What is the most appropriate way to achieve that?
For example my custom group is MY_CUSTOM_GROUP and i want to add change and view permissions for Model Book to that group
Just ran into that problem myself. The standard way to do it is either by creating a custom migration or through fixtures. Groups and permissions added through a custom migration will be available without any additional commands. The downside might be that the process of migrations rebuild will now be more complicated (I am a noob at django too, so please correct me if I'm wrong here). Fixtures require running a manage.py command to prepopulate the database, but they come with the advantage of being completely decoupled from migrations.

Using django south with a different set of database credentials

I'm building a Django app which connects to a PostgreSQL database, and the credentials that the app uses has quite limited permissions granted over the relevant tables.
I'd like to be able to use south to manage database migrations, but given that this picks up on the same credentials that Django uses, this throws an error as south cannot make any changes to tables it doesn't own.
Is there a way to specify that south should use a different set of credentials to manage migrations other than that specified by the application settings?
Yes : have another set of settings with different credentials for south migrations and use the --settings option when calling the migrate command.
NB : to avoid DRY violation, you can as well start your special settings file by importing * from the normal settings and just override the DB credentials.

"Django documentation" says "ensure that Django has permission to create and alter tables" so how do I do that in postgreSQL?

I'm taking EdX classes that use Ruby on Rails and python. That has given me courage to try and install and learn Django using Apach, mod_wsgi, and PostgreSQL. Following the detailed installation instructions, I first installed Apache, then mod_wsgi, and then PostgreSQL. I installed each from source and went through a little bit of tutorial with each and made sure they were properly installed. I've got a postgres user setup to run the PostgreSQL server and I was able to create a user "role" for myself as well as an admin role that my role inherits from that can create a database etc. I tried out some SQL in psql following a tutorial to make tables etc. I know how to grant privileges for a given role.
So anyway, I'm pretty close to the step where I would actually install Django from source, but I'm not sure how to follow this advice from the installation instructions:
If you plan to use Django's manage.py syncdb command to automatically create database tables for your models, you'll need to ensure that Django has permission to create and alter tables in the database you're using; if you plan to manually create the tables, you can simply grant Django SELECT, INSERT, UPDATE and DELETE permissions.
Maybe after I follow the steps to actually install Django and go through some tutorials, I'll understand exactly what needs to be setup in PostgreSQL to grant Django those permissions, but if I follow the installation instructions in order, it would seem to be saying I should setup those permissions now before installing Django. If I can get someone to tell me how to do it here before I do the install of Django, I'd appreciate it.
In the settings.py file of a django project, there is a snippet that says something like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproj_db',
'USER': 'myproj_user',
'PASSWORD': '123',
'HOST': '',
'PORT': '',
},
}
What this does is that it tells Django what user (postgres user in this case) and database is used in conjunction with your django project.
Normally, you will need to create this myproj_user together with the myproj_db.
When you create this user, you can choose to give it permissions like so:
CREATE USER myproj_user WITH PASSWORD '123' SUPERUSER CREATEDB CREATEROLE LOGIN;
This creates the myproj_user with superuser, createdbm createrole, login permissions allowed to the user.
And then the database like so:
CREATE DATABASE myproj_db WITH OWNER myproj_user TEMPLATE=template1 ENCODING='utf-8';
You say that you know how to grant privileges for a given role, which is what you need to do for Django before installing it (running syncdb).
This is part of setting up your database for use with Django – a step you take before creating each Django project. Each Django project corresponds to a site that you build with Django and is completely separate from another Django project. To each project belongs a database.* You can install Django the framework before you setup your database, because Django the framework doesn't do anything on its own.
Either you give Django permissions to create tables for you, in which case it can create tables for you (using manage.py syncdb). Or, you use manage.py sqlall <app> to get SQL that you run yourself to create the tables needed (which might be nice if you're paranoid about security).
To grant all permissions to a user for a specific database (option 1) in Postgres, use the command (from psql):
GRANT ALL PRIVILEGES ON DATABASE <db-name> TO <username>;
* Technically, they can share a database by simply configuring them to use the same one.
Django uses ORM (Object Relational Mapper). What that means is that you do not directly deal with database tables for querying things however you deal with certain classes which then deal with the database. This is very useful and much more user-friendly then doing manually SQL. Consider the following example:
SELECT * FROM foo WHERE field="value"
vs
Foo.objects.filter(field='value')
In ORM, you describe the tables you have by making certain classes (in Django we call them models) and those models correspond to tables in the db, and their fields correspond to the columns in the db table. The following are very similar:
CREATE TABLE foo (
title varchar(50),
description text,
likes integer
);
and
class Foo(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
likes = models.IntegerField()
However it is waste of time for you as a developer to construct the SQL statements for creating tables, and describing those tables in Python as models. Not to do that, Django allows you once you define all your models, to create db tables for you. That is the purpose of the syncdb command. It takes all the installed apps and models within them and creates tables within your database for them. However as you already mentioned in your question, databases have roles and those roles have permissions. For example, one of the permissions is CREATE as described here. So what Django documentation is saying is for you to grand all necessary permission to a role which Django will use to interact with the db for Django to be able to create necessary db tables it needs as well as possibly modify them later.

Tying a model to a specific database alias

I have defined two databases in my settings.py with default, cas.
In my accounts application models.py I have created two clases
UserProfile and Users.
I want to tie UserProfile table to default and Users to cas db setting:
so for e.g. when I do a syncdb using the following command
python manage.py syncdb --database=cas
it should create only the users table in CAS and not the UserProfile table too.
Is there a way I can achieve this?
Take a look at the Database routing features of Django 1.2. You'll likely find what you need:
http://docs.djangoproject.com/en/dev/topics/db/multi-db/#automatic-database-routing