How to get signals.py executed in django? - python-3.x

I run the following signals.py on (Ubuntu2204/WSL2 Windows 11) using Django 4.1.1 / Python 3.10
from .models import Sale
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
#receiver(m2m_changed, sender=Sale.positions.through)
def calculate_total_price(sender, instance, action, **kwargs):
print('action', action)
total_price = 0
if action == 'post_add' or action == 'post_remove':
for item in instance.get_positions():
total_price += item.price
instance.total_price = total_price
instance.save()
apps.py already signals in VSCode that signals is not used, this is also confirmed in the Django Debug Toolbar
from django.apps import AppConfig
class SalesConfig(AppConfig):
#default_auto_field = 'django.db.models.BigAutoField'
name = 'sales'
def ready(self):
import sales.signals
and then the __init__.py file
default_app_config = 'sales.apps.SalesConfig'
settings.py looks like this:
"""
Django settings for reports_proj project.
Generated by 'django-admin startproject' using Django 4.1.1.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-dbl^hk-m6-dz01+1i*hi5#rz4t90(y5s-cls1&0js5hj^ojo70"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"debug_toolbar",
# my apps
"customers",
"products",
"profiles",
"reports",
"sales.apps.SalesConfig",
# 3rd party
"crispy_forms",
]
CRISPY_TEMPLATE_PACK = "bootstrap4"
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"debug_toolbar.middleware.DebugToolbarMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "reports_proj.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / 'templates'],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "reports_proj.wsgi.application"
# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
BASE_DIR / 'sales' / 'static',
]
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
INTERNAL_IPS = [
"127.0.0.1",
]
Any hint would be highly appreciated, the code looks ok to me it must be some dependency issue but I have no idea where to start looking really

I just noticed that your ready identation is not correct, causing the problem...
You should change this:
from django.apps import AppConfig
class SalesConfig(AppConfig):
#default_auto_field = 'django.db.models.BigAutoField'
name = 'sales'
def ready(self):
import sales.signals
To this:
from django.apps import AppConfig
class SalesConfig(AppConfig):
#default_auto_field = 'django.db.models.BigAutoField'
name = 'sales'
def ready(self):
from . import signals
Generally because no indentation the method became global function and it was not called as it should.

Related

No installed app with label 'polls' - activating models - error

I am learning Django3.2.5, from https://docs.djangoproject.com/en/3.2/intro/tutorial02/. I created a project with the name, 'mysite', then 'polls' app, and using the default 'SQLite' database.
Project's (mysite) file hierarchy:
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
App's (polls) file hierarchy:
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
mysite/mysite/settings.py
"""
Django settings for mysite project.
Generated by 'django-admin startproject' using Django 1.11.29.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '4)2m9i5*y=icl-9bpiw#w#n!(y^y%38+8smh70mqupeppb&o#r'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'mysite.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'mysite.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
mysite/polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
mysite/polls/apps.py
from django.apps import AppConfig
class PollsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'polls'
When I run, python3 manage.py makemigrations polls, it throws out this error No installed app with label 'polls'.
I am new to Django, please help.
In Installed apps
you have written this
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
'polls.apps.PollsConfig', it is wrong syntax
instead of this write
INSTALLED_APPS = [
...
'polls.apps.PollsAppConfig',
...
]
Try python manage.py makemigrations
Without using 'polls'

Flask API - create nested json response group by field single table

I have a basic API setup to do a basic Post and Get from a single table. I want to create a nested array though grouping by force_element_type
model.py
from db import db
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy import text as sa_text
class ForceElementModel(db.Model):
__tablename__ = 'force_element'
__table_args__ = {'schema': 'force_element'}
force_element_id = db.Column(UUID(as_uuid=True), primary_key=True, server_default=sa_text("uuid_generate_v4()"))
name = db.Column(db.String(100), nullable=False)
force_element_type = db.Column(db.String(20), nullable=False)
def __init__(self, name, force_element_type):
self.name = name
self.force_element_type = force_element_type
def json(self):
return {'name': self.name, 'force_element_type': self.force_element_type}
#classmethod
def find_by_name(cls, name):
return cls.query.filter_by(name=name).first() # simple TOP 1 select
def save_to_db(self): # Upserting data
db.session.add(self)
db.session.commit() # Balla
def delete_from_db(self):
db.session.delete(self)
db.session.commit()
resource.py
from flask_restful import Resource, reqparse
#from flask_jwt import jwt_required
from models.force_element import ForceElementModel
class ForceElement(Resource):
parser = reqparse.RequestParser() # only allow price changes, no name changes allowed
parser.add_argument('force_element_type', type=str, required=True, help='This field cannot be left blank')
##jwt_required()
def post(self, name):
if ForceElementModel.find_by_name(name):
return {'message': "An Force Element with name '{}' already exists.".format(name)}, 400
data = ForceElement.parser.parse_args()
force_element = ForceElementModel(name, data['force_element_type'])
try:
force_element.save_to_db()
except:
return {"message": "An error occurred inserting the item."}, 500
return force_element.json(), 201
class ForceElementList(Resource):
##jwt_required()
def get(self):
return {'force_elements': [force_element.json() for force_element in ForceElementModel.query.all()]}
class ForceElementType(Resource):
##jwt_required()
def get(self):
The GET endpoint using ForceElementList returns
{
"force_elements": [
{
"name": "San Antonio",
"force_element_type": "ship"
},
{
"name": "Nimitz",
"force_element_type": "ship"
},
{
"name": "Nimitz- Starboard",
"force_element_type": "Crew"
},
{
"name": "Nimitz- Port",
"force_element_type": "Crew"
}
]
}
I don't know how to group by force_element_type and return
[
"ship": [
{
"name": "San Antonio",
"force_element_id": "xxx1"
},
{
"name": "Nimitz",
"force_element_id": "xxx2"
}],
"crew": [
{
"name": "Nimitz- Starboard",
"force_element_id": "yyy1"
},
{
"name": "Nimitz- Port",
"force_element_id": "yyy2"
}
]
]
How do I create this separate andpoint?
OK I got there, here is how I did it. Is there a better way?
Lesson one use an online parser to check the json format this is what I was actually aiming for and the square braket at then start had me scratching my head for a while
{
"ship": [
{
"name": "San Antonio",
"force_element_id": "xxx1"
},
{
"name": "Nimitz",
"force_element_id": "xxx2"
}],
"crew": [
{
"name": "Nimitz- Starboard",
"force_element_id": "yyy1"
},
{
"name": "Nimitz- Port",
"force_element_id": "yyy2"
}]
}
This code creates the correct format for the output
class ForceElementType(Resource):
##jwt_required()
def get(self):
types = {}
force_elements = ForceElementModel.query.order_by(ForceElementModel.force_element_type.desc()).all()
for force_element in force_elements:
nested = {'name': force_element.name, 'force_element_id': str(force_element.force_element_id)}
print(nested)
if not force_element.force_element_type in types:
types[force_element.force_element_type] = []
types[force_element.force_element_type].append(nested)
response = types

moto testing for ecs

I have a python method that lists certain ECS Fargate services based on some tags and some names using boto3 get_paginator.
def list_service_name(environment,
resource_owner_name,
ecs_client):
list_of_service = list()
cluster_name = "my cluster name " + environment
target_string = "-somedummy"
resource_owner_tag = resource_owner_name
service_paginator = ecs_client.get_paginator('list_services')
for page in service_paginator.paginate(cluster=cluster_name,
launchType='FARGATE'):
for service in page['serviceArns']:
response = ecs_client.list_tags_for_resource(resourceArn=service)
for tags in response['tags']:
if tags['key'] == 'ResourceOwner' and \
tags['value'] == resource_owner_tag and \
service.endswith(target_string):
list_of_service.append(service)
return list_of_service
Now I would like to test this using moto.
Hence I have created conftest.py where I have defined all moto mock connections to the services like, ecs. Also, I have created test_main.py file like below where I have created dummy services connected to ECS Fargate. But for some reason, if I try to assert the outcome of the main method in the test file the service lists return empty. Whereas I would like to see test-service-for-successful as the outcome. Is there something I'm missing or pagination is still not available in moto?
from my_code.main import *
#pytest.fixture
def env_name():
return "local"
#pytest.fixture
def cluster_name(env_name):
return "my dummy" + env_name + "cluster_name"
#pytest.fixture
def successful_service_name():
return "test-service-for-successful"
#pytest.fixture
def un_successful_service_name():
return "test-service-for-un-successful"
#pytest.fixture
def resource_owner():
return "dummy_tag"
#pytest.fixture
def test_create_service(ecs_client,
cluster_name,
successful_service_name,
un_successful_service_name,
resource_owner):
_ = ecs_client.create_cluster(clusterName=cluster_name)
_ = ecs_client.register_task_definition(
family="test_ecs_task",
containerDefinitions=[
{
"name": "hello_world",
"image": "docker/hello-world:latest",
"cpu": 1024,
"memory": 400,
"essential": True,
"environment": [
{"name": "environment", "value": "local"}
],
"logConfiguration": {"logDriver": "json-file"},
}
],
)
ecs_client.create_service(
cluster=cluster_name,
serviceName=successful_service_name,
taskDefinition="test_ecs_task",
desiredCount=0,
launchType="FARGATE",
tags=[{"key": "resource_owner", "value": resource_owner}]
)
ecs_client.create_service(
cluster=cluster_name,
serviceName=un_successful_service_name,
taskDefinition="test_ecs_task",
desiredCount=0,
launchType="FARGATE",
tags=[{"key": "resource_owner", "value": resource_owner}]
)
yield
def test_list_service_name(env_name,
resource_owner,
ecs_client):
objects = list_service_name(env_name,
resource_owner,
ecs_client)
# here object is []
# Where as I should see successful_service_name

flask-marshmallow custom fields

I use flask-marshmallow and mongoengine.
Also flask-restplus for my API server.
Here is my api.py
class BoardSchema(ma.Schema):
class Meta:
fields = ('no', 'title', 'body', 'tags', 'created_at', 'views')
board_schema = BoardSchema()
boards_schema = BoardSchema(many=True)
class ArticleList(Resource):
def get(self):
articles = Board.objects.all()
return boards_schema.jsonify(articles)
model.py
from datetime import datetime
from mongoengine import *
from config import DB_NAME
connect(DB_NAME)
class Board(Document):
d = datetime.now()
date = "{}-{}-{}".format(d.year, d.month, d.day)
no = SequenceField()
title = StringField(required=True)
body = StringField(required=True)
tags = ListField(StringField())
likes = ListField(StringField())
views = ListField(StringField())
password = StringField(required=True)
created_at = DateTimeField(default=date)
updated_at = DateTimeField(default=date)
When I access to /article, it's result like this ->
{
"body": "123",
"created_at": "2018-08-20T00:00:00+00:00",
"no": 1,
"tags": [
"MySQL",
"C"
],
"title": "\ud14c\uc2a4\ud2b8",
"views": [
"127.0.0.1"
]
}
in "views", ip will be added who read article.
But I want to count of all the list of views and include it to my result.
The result I wanted is here.
{
"body": "123",
"created_at": "2018-08-20T00:00:00+00:00",
"no": 1,
"tags": [
"MySQL",
"C"
],
"title": "\ud14c\uc2a4\ud2b8",
"views": 20
}
I'm new at flask-marshmallow so I'm so confused how can I solve this issue.
Thanks.
Maybe you can try like this:
class BoardSchemaCustom(ma.ModelSchema):
class Meta:
model = Board
views = ma.fields.method(deserialize="_custom_serializer")
def _custom_serializer(self, obj):
return len(obj.views)
Create instance of your custom schema:
custom_board_schema = BoardSchemaCustom()
and dump it:
dump, errors = custom_board_schema.schema.dump(Board.query.first())
>>> dump
i've got the same problem. and my code works after installing marshmallow-sqlalchemy
pip install marshmallow-sqlalchemy
see from offical documentation
https://flask-marshmallow.readthedocs.io/en/latest/
Below snippet would also work:
class BoardSchemaCustom(ma.ModelSchema):
class Meta:
model = Board
views = ma.fields.Function(lambda obj: len(obj.views))

Migrating from WAF to GYP - trouble including library

I'm migrating an out of date npm package from WAF to GYP, but having a few problems getting everything working. It runs a WSCRIPT which seems to include a 3rd party library:
import Options
from os import unlink, symlink, popen, sys
from os.path import exists
srcdir = '.'
blddir = 'build'
VERSION = '0.0.2'
def set_options(opt):
opt.tool_options('compiler_cxx')
def configure(conf):
conf.check_tool('compiler_cxx')
conf.check_tool('node_addon')
print(sys.platform)
if sys.platform == 'darwin':
conf.check_tool('osx')
tc_framework = 'TelldusCore'
conf.env.append_value("FRAMEWORK_TC", tc_framework)
tc_frameworkpath = '/Library/Frameworks/TelldusCore.framework/'
conf.env.append_value("FRAMEWORKPATH_TC", tc_frameworkpath)
tc_lib = tc_frameworkpath + 'Headers/'
conf.env.append_value("CPPPATH_TC", tc_lib)
elif sys.platform == 'linux2':
conf.env.LIB_TC = 'telldus-core'
#conf.env.LIBPATH_TC = ['/usr/lib']
#conf.env.CCFLAGS_TC = ['-O0']
conf.env.CCDEFINES_TC = ['TC']
#conf.env.LINKFLAGS_TC = ['-g']
else:
raise ValueError("Dose not support: %r" % sys.platform)
def build(bld):
obj = bld.new_task_gen('cxx', 'shlib', 'node_addon')
obj.target = 'telldus'
obj.source = 'telldus.cc'
obj.uselib = "TC"
Now I've tried to convert it to a binding.gyp script, but not sure how to include the library:
{
"targets": [
{
"target_name": "tellduscorejs2",
"sources": [ "tellduscorejs2.cpp" ],
"conditions": [
['OS=="mac"', {
'defines': [
'FRAMEWORK_TC=TelldusCore',
'FRAMEWORKPATH_TC="/Library/Frameworks/TelldusCore.framework/"',
'CPPPATH_TC="/Library/Frameworks/TelldusCore.framework/Headers/"'
]
}],
['OS=="linux"', {
'defines': [
'LIB_TC=telldus-core',
'CCDEFINES_TC=TC'
]
}]
],
'link_settings': {
'libraries': [
???
],
},
}
]
}
If anyone could point out if I'm on the right lines or what I need to change to include the library it'd be appreciated!
I've actually done this for the telldus-core project. See https://github.com/marchaos/telldus-core-js/
i've also added events for devices and sensors.

Resources