Django Cant access auth User, Group object in custom data migration - django

My migration file looks like this:
from __future__ import unicode_literals
from django.db import migrations
from project.tools import do_nothing
def create_can_receive_group(apps, schema_editor):
Group = apps.get_model("django.contrib.auth", 'Group')
# Group operation added here
class Migration(migrations.Migration):
dependencies = [
('poreceiving', '0004_auto_20150616_0846'),
('django.contrib.auth', '0006_require_contenttypes_0002')
]
operations = [
migrations.RunPython(create_can_receive_group, do_nothing),
]
Here I want to access Group object of django.contrib.auth.
I get the following exception.
*** LookupError: No installed app with label 'django.contrib.auth'.
I found somewhere that if we want to use other object which is not in app in which the migration is present then we should add latest migration of other app.
When I add django.contrib.auth latest migration to the dependency I get following :
django.db.migrations.graph.NodeNotFoundError: Migration poreceiving.0005_create_can_receive_group dependencies reference nonexistent parent node (u'django.contrib.auth', u'0006_require_contenttypes_0002')

Try something like this (look at the migrations.swappable_dependency part in the dependencies):
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations
from project.tools import do_nothing
def create_can_receive_group(apps, schema_editor):
Group = apps.get_model("auth", "Group")
# Group operation added here
class Migration(migrations.Migration):
dependencies = [
('poreceiving', '0004_auto_20150616_0846'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RunPython(create_can_receive_group, do_nothing),
]

Related

django: adding custom permissions stopped working

I have a django project with multiple apps. In one of the apps when I add custom permissions to any model and run makemigration, the migration-file to add the permission is created. When I apply the migration I get no error messages but the permission isn't added to the auth_permission table.
class Meta:
app_label = 'my_app'
permissions = (
('assign_work_type', 'Assign work type'),
)
The migration completes without errors
I have tried doing the same in other apps and that works. I have also tried adding a column to the current app and that works as well. Anyone got any idea what it could be? I am running django 1.11.26
UPDATE
Here is the content of the migration file
# -*- coding: utf-8 -*-
# Generated by Django 1.11.26 on 2019-11-25 11:13
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('timereport', '0143_auto_20191122_1754'),
]
operations = [
migrations.AlterModelOptions(
name='worktype',
options={'permissions': (('assign_work_type', 'Assign work type'),)},
),
]
After quite some investigation I found that the affected app was missing the models_module, i.e. the "models.py" file. I have all my models in a /model/ directory and a while back I deleted the models.py file thinking it was of no use.
Adding the models.py file back solved the issue

How to add a permission to a user/group during a django migration?

I would like to execute the following migration:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth.models import Permission
from django.db import migrations
from django.conf import settings
from django.contrib.auth.models import Group, User
def add_api_group(apps, schema_editor):
Group.objects.create(name=settings.API_USER_GROUP)
# get_or_create returns a tuple, not a Group
group = Group.objects.get(name=settings.API_USER_GROUP)
permissions = Permission.objects.filter(codename__in = [
'add_topic',
])
group.permissions.add(*permissions)
def add_api_user(apps, schema_editor):
user = User.objects.create_user(username=settings.API_USER, password=settings.API_USER_PASSWORD)
group = Group.objects.get(name=settings.API_USER_GROUP)
user.groups.add(group)
class Migration(migrations.Migration):
dependencies = [
('nd_content', '0001_initial'),
]
operations = [
migrations.RunPython(add_api_group),
migrations.RunPython(add_api_user)
]
At the last line of the migration, I issued an error to stop execution and look at the database state. The problem is the table auth_permission still has not the permissions of a model of another module, although this other module is registered as a dependecy of this migration.
I can confirm missing permissions seem to be added only after all migrations have been executed.
AttributeError: 'StateApps' object has no attribute 'label' in Django 1.10
There is a solution:
for app_config in apps.get_app_configs():
app_config.models_module = True
create_permissions(app_config, verbosity=0)
app_config.models_module = None
EDIT 2018-01-31
This answer will only work until Django 1.9. For Django 1.10 an up, please refer to the answer provided by #anton-lisenkov
Original Answer (Django<1.10)
It turns out I could do the following:
from django.contrib.auth.management import create_permissions
def add_permissions(apps, schema_editor):
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
Thanks #elad-silver for his answer: https://stackoverflow.com/a/34272647/854868
If you don't have to attach your permission to a personal model you can do it this way:
from django.contrib.auth.models import Permission, ContentType
def add_permission(apps, schema_editor):
content_type = ContentType.objects.get(app_label='auth', model='user') # I chose user model but you can edit it
permission = Permission(
name='Your permission description',
codename='your_codename',
content_type=content_type,
)
permission.save()

Django rest framework No module named .serializers

For some reason my serialize module is not being recognized, any ideas why this is? I have installed rest_framework and have it in my settings.py file under apps.
For some reason though my serializer.py file is showing rest_framework import is 'unresolved', not sure why this is or if that is the cause of the problem but I have had that before where my editor seems to sometimes mark imports as unresolved but still work.
Here is my serializes.py
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework import routers, serializers, viewsets, permissions
from .models import Part, Supplier, SupplierPart
class PartSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Part
field = [
'id',
'name',
'code',
]
class SupplierSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Supplier
field = [
'id',
'name',
]
class SupplierPartSerializer(serializers.HyperlinkedModelSerializer):
part = PartSerializer()
supplier = SupplierSerializer()
class Meta:
model = SupplierPart
field = [
'id',
'part',
'supplier',
'supplier_code',
'description',
'price',
'sale_price',
'quantity',
'photo',
'url',
]
class SupplierPartViewSet(viewsets.ModelViewSet):
queryset = SupplierPart.objects.all()
serializer_class = SupplierPartSerializer
Here is my URls:
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
from rest_framework import routers
from SupplierPart.serializers import SupplierPartViewSet
router = routers.DefaultRouter()
router.register(r"SupplierPart", SupplierPartViewSet)
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^search/', include('haystack.urls')),
url(r'^$', include('haystack.urls')),
url(r'^part/', include('products.urls')),
url(r'^api/', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
I am getting this error though when I try to go to my site
---->>>>>>>>>>>>
use "from rest_framework.serializers import *"
i resolved this error by replace
"from rest_framework import serializers"
with
"from rest_framework.serializers import *"
about the unresolved imports: are you using a virtualenv? if so, be sure your IDE is using it as interpreter.
As I understand from your code, SupplierPart is a model. And you are trying to import serializers from it in your urls.py file.
When, you should import it from the app. For example. if your serializers.py is located in suppliers app (folder/package) then you should import it like this:
from suppliers.serializers import SomeSerializer
P.S.
serializers.py file is supposed to hold Serializers, not ViewSets
If your serializers are in different folder nested somewhere in your app in django and you get this error even though the import seems to be okay,
try to create inside the nested folder empty file and call it __init__.py.
For example:
if I have chat app inside django project and want to seperate my serializers into different folder which I will call serializers it will look like this:

right way to create a django data migration that creates a group?

I would like to create data migrations that create Permissions and Groups, so that my other developers can just run the migrations and get everything set up. I was able to create the migrations and run them just fine, but now I'm getting an error when running my tests.
But if I do this:
from django.contrib.auth.models import Group
def add_operations_group(apps, schema_editor):
Group.objects.get_or_create(name='operations')
I get:
django.db.utils.OperationalError: no such table: auth_group
If I do this:
def add_operations_group(apps, schema_editor):
Group = apps.get_model("django.contrib.auth", "group")
Group.objects.get_or_create(name='operations')
I get:
LookupError: No installed app with label 'django.contrib.auth'
Is there a way to do this? Or is there a "Django Way" to make sure things like permissions and groups are created?
This is how I do it:
from django.db import models, migrations
def apply_migration(apps, schema_editor):
Group = apps.get_model('auth', 'Group')
Group.objects.bulk_create([
Group(name=u'group1'),
Group(name=u'group2'),
Group(name=u'group3'),
])
def revert_migration(apps, schema_editor):
Group = apps.get_model('auth', 'Group')
Group.objects.filter(
name__in=[
u'group1',
u'group2',
u'group3',
]
).delete()
class Migration(migrations.Migration):
dependencies = [
('someapp', 'XXXX_some_migration'),
]
operations = [
migrations.RunPython(apply_migration, revert_migration)
]
Although, there must be a more Djangonic way.
Answer from César is correct. To make it more Django create the migration file automatically by going to your django app root folder and entering:
python manage.py makemigrations <yourappname> --empty
Note: You may need python3 instead of python depending on your system configuration.
This creates an empty migration file in a sub directory of your app called 0001_initial.py
You can then alter it as per César instructions. Which worked correctly with Django 2.2

django: data migrate permissions

I have a bunch of new permissions which I need to migrate. I tried doing it through data migration but complains about ContentType not being available.
Doing quick research I found out that ContentType table is populated after all the migrations applied.
I even tried using update_all_contenttypes() from from django.contrib.contenttypes.management import update_all_contenttypes
which causes migration to load data which is not consistent to the fixture.
What is the best way to migrate permission data in Django?
Here is a quick and dirty way to ensure all permissions for all apps have been created:
def add_all_permissions(apps=None, schema_editor=None):
from django.contrib.auth.management import create_permissions
if apps is None:
from django.apps import apps
for app_config in apps.get_app_configs():
app_config.models_module = True
create_permissions(app_config, verbosity=0)
app_config.models_module = None
class Migration(migrations.Migration):
dependencies = [('myapp', '0123_do_the_thing')]
operations = [
migrations.RunPython(add_all_permissions,
reverse_code=migrations.RunPython.noop)
# ...
]
NOTE: edited to include ruohola's excellent suggestion
There are 2 ways to solve this:
1) The ugly way:
Run manage.py migrate auth before your wanted migration
2) Recommended way:
from django.contrib.auth.management import create_permissions
def add_permissions(apps, schema_editor):
apps.models_module = True
create_permissions(apps, verbosity=0)
apps.models_module = None
# rest of code here....
Here are steps for adding custom permissions to the User model:
First create a migration file, for example under your authentication application,
Here i named it 0002_permission_fixtures.py:
account (your authentication application)
|_migrations
|__ 0001_initial.py
|__ 0002_permission_fixtures.py
|__ __init__.py
Then adding your permission objects, as follow:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def forwards_func(apps, schema_editor):
# Get models that we needs them
user = apps.get_model("auth", "User")
permission = apps.get_model("auth", "Permission")
content_type = apps.get_model("contenttypes", "ContentType")
# Get user content type object
uct = content_type.objects.get_for_model(user)
db_alias = schema_editor.connection.alias
# Adding your custom permissions to User model:
permission.objects.using(db_alias).bulk_create([
permission(codename='add_sample', name='Can add sample', content_type=uct),
permission(codename='change_sample', name='Can change sample', content_type=uct),
permission(codename='delete_sample', name='Can delete sample', content_type=uct),
])
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '__latest__'),
]
operations = [
migrations.RunPython(
forwards_func,
),
]
To run this migration, first migrate contenttype model, and then migrate your application (here is account).
$ python manage.py migrate contenttypes
$ python manage.py migrate account