Have gone through
Django 1.9 deprecation warnings app_label
but answers couldn't fix my problem, so asking again.
I have an app that is added to INSTALLED_APPS in settings.
when ever I run manage.py runserver, I get this warning,
[trimmed path to project]/catalog/models.py:9: RemovedInDjango19Warning: Model class catalog.models.Category doesn't declare an explicit app_label and either isn't in an application in INSTALLED_APPS or else was imported before its application was loaded. This will no longer be supported in Django 1.9.
class Category(models.Model):
The code from my app,
signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from models import Category
#receiver(post_save, sender=Category)
def someSignal(sender, **kwargs):
pass
apps.py
from django.apps import AppConfig
class CatalogConfig(AppConfig):
name = 'catalog'
verbose_name = 'Catalogue'
init.py
import signals
default_app_config = 'catalog.apps.WhosConfig'
Django version 1.8.2 on Python 2.7.8
I experienced this issue when running tests and it was simply a matter of changing:
from .models import MyModel
to
from apps.myapp.models import MyModel
You are importing models.py before app configuration run.
To fix it, you could import and configure signals in CatalogConfig.ready method.
like this:
signals.py
def someSignal(sender, **kwargs):
pass
apps.py
from django.apps import AppConfig
from django.db.models.signals import post_save
class CatalogConfig(AppConfig):
name = 'catalog'
verbose_name = 'Catalogue'
def ready(self):
from .signals import someSignal
post_save.connect(
receiver=someSignal,
sender=self.get_model('Category')
)
you may want to check ready method in documentation
Related
I am creating a web app with Django.
I wrote the following codes to add 1 data per minute to the table using APScheduler. When I checked the data generated by APScheduler on the Django admin panel, I found that 3 data were generated per minute for some reason.
why does this happen? and how can i solve it?
# models.py
from django.db import models
class Test(models.Model):
test = models.CharField(max_length=8)
created_at = models.DateTimeField(auto_now_add=True)
# admin.py
from django.contrib import admin
from .models import Test
class TestAdmin(admin.ModelAdmin):
list_display = ('test', 'created_at')
admin.site.register(Test, TestAdmin)
# ap_scheduler.py
from apscheduler.schedulers.background import BackgroundScheduler
from .models import Test
def myfunc():
Test.objects.create(test='test')
def start():
scheduler = BackgroundScheduler()
scheduler.add_job(myfunc, 'cron', second=50)
scheduler.start()
# apps.py
from django.apps import AppConfig
class MembersConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'my_app_name'
def ready(self):
from .ap_scheduler import start
start()
バージョン情報
APScheduler==3.9.1
Django==4.0.5
You probably have multiple schedulers due to the auto-reloader is calling the start() command more then once. Try running with:
python manage.py runserver --noreload
In my Django app, I have an abstract model called MyModel that has e.g. created_at and updated_at fields. I want all the models in my project to subclass MyModel rather than using django.db.models.Model directly.
We have several developers on our app, so I want to use some sort of linter or CI check to enforce that this happens. How can I do this?
As mentioned by Willem Van Onsem in their comment you can write your own checks using the System check framework.
Assuming we have the following models in an app named "checktest" with Parent being the model that all models should inherit from:
from django.db import models
class Parent(models.Model):
class Meta:
abstract = True
# This should raise an error
class Foo(models.Model):
pass
# This should be fine
class Bar(Parent):
pass
We'll write a check as follows in a file checktest/custom_checks.py, note that the list APPS_TO_TEST contains the names of the apps whose models should inherit from the parent class:
from django.apps import apps
from django.core.checks import Error, register, Tags
from .models import Parent
# List of apps that should inherit from Parent
APPS_TO_TEST = ["checktest"]
#register(Tags.models)
def model_must_inherit(app_configs, **kwargs):
errors = []
for app in APPS_TO_TEST:
models = apps.get_app_config(app).get_models()
for model in models:
if not issubclass(model, Parent):
errors.append(Error(
f"Model {model.__name__} does not inherit from Parent",
hint="Models must inherit from the Parent class",
obj=model,
id="checktest.E001"
))
return errors
In the app configs ready method we'll import the above file so that the check will get run:
from django.apps import AppConfig
class ChecktestConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'checktest'
def ready(self) -> None:
from . import custom_checks
Now whenever we run commands like runserver or migrate the checks will get implicitly run. In a CI environment you can explicitly run the checks using the check command.
I have just broken up my models.py in to a module as follows:
models/
__init__.py
model1.py
model2.py
userModel.py
....
Where init.py imports all of the classes so I can still get at them using models.model1 as follows
from model1 import model1
from model2 import model2
from userModel import userModel
This is working ok however Django can no longer find the AUTH_USER_MODEL using:
AUTH_USER_MODEL = 'app.userModel'
I get the error:
LookupError: App 'app' doesn't have a 'userModel' model.
I have tried to change this to
AUTH_USER_MODEL = 'app.models.userModel'
but this doesn't work either. Any advice much appreciated
Jack
AUTH_USER_MODEL = 'app.UserModel'
UserModel is supposed to be a class that inherits from models.Model, not a module.
It will be passed through django.apps.apps.get_model(settings.AUTH_USER_MODEL) that takes a string app.Model where app is a django app registered in INSTALLED_APPS and Model is any model within app.models module and submodules.
Edit
Before Django 1.9, your models lying in a sub-module of app_name.models should define app_label = 'app_name' in their metaclass:
class MyUser(models.Model):
class Meta:
app_label = 'app_name'
Trying to use django-image-cropping. I don't get any errors, I just have what looks like CharField in Django Admin instead of the django-image-cropping functionality:
base.py (settings):
from easy_thumbnails.conf import Settings as thumbnail_settings
THUMBNAIL_PROCESSORS = (
'image_cropping.thumbnail_processors.crop_corners',
) + thumbnail_settings.THUMBNAIL_PROCESSORS
added easy_thumbnails and image_cropping to INSTALLED_APPS
models.py:
from image_cropping import ImageRatioField
# ...
class Organization(models.Model):
image_cover = models.ImageField(upload_to='media', blank=True, help_text="blah")
cropping = ImageRatioField('image_cover', '308x850')
admin.py:
from django.contrib import admin
from image_cropping import ImageCroppingMixin
class OrganizationAdmin(ImageCroppingMixin, admin.ModelAdmin):
pass
class OrganizationAdmin(admin.ModelAdmin):
filter_horizontal=['categorys']
#...
admin.site.register(Organization, OrganizationAdmin)
You're defining OrganizationAdmin twice in admin.py. Once, correctly, subclassing ImageCroppingMixin and once without. Since the latter definition overwrites the former, you end up without the Mixin. This is how it should look like:
from django.contrib import admin
from image_cropping import ImageCroppingMixin
class OrganizationAdmin(ImageCroppingMixin, admin.ModelAdmin):
filter_horizontal=['categorys']
#...
admin.site.register(Organization, OrganizationAdmin)
I'm attempting to work my way through Practical Django Projects. It seems to be a bit old, but I've manage to convert the code up to this point.
At this point the book would like me to change my models.py to be this:
class SearchKeyword(models.Model)
keyword = models.CharField(maxlength=50, core=True)
page = models.ForeignKey(FlatPage, edit_inline=models.STACKED,
min_num_in_admin=3, num_extra_on_change=1)
I know that this is now done in the admin.py instead. So my models.py looks like this:
from django.db import models
from django.contrib.flatpages.models import FlatPage
class SearchKeyword(models.Model):
keyword = models.CharField(max_length=50)
page = models.ForeignKey(FlatPage)
class Admin:
pass
def __unicode__(self):
return self.keyword
And the admin.py I've created now looks like this:
from search.models import SearchKeyword
from django.contrib import admin
from django.contrib.flatpages.models import FlatPage
class SearchKeywordInline(admin.StackedInline):
model = SearchKeyword
extra = 3
class FlatPageAdmin(admin.ModelAdmin):
model = FlatPage
inlines = [SearchKeywordInline]
admin.site.register(FlatPage, FlatPageAdmin)
When I load the Admin page, I receive:
AlreadyRegistered at /admin/
The model FlatPage is already registered
Exception Value:The model FlatPage is already registered
Thank you!
You have to unregister it first as the app itself ships with an admin.py
admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin)