Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to configure Auth, compains about INSTALLED_APPS #34

Open
koaning opened this issue Sep 29, 2024 · 4 comments
Open

How to configure Auth, compains about INSTALLED_APPS #34

koaning opened this issue Sep 29, 2024 · 4 comments

Comments

@koaning
Copy link
Contributor

koaning commented Sep 29, 2024

I am trying to run the following app.

from django.db import models
from nanodjango import Django

from django.db.models import Model
from django.contrib.auth.models import User
from django.http import HttpRequest
import secrets
import json


app = Django(DEBUG=True, EXTRA_APPS=["django.contrib.auth"])


@app.admin
class LoggedItem(Model):
    collection = models.TextField()
    data = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def get_collection(self):
        return json.loads(self.collection)

    def __str__(self):
        return f"LoggedItem {self.id} created at {self.created_at}"


@app.admin
class APIKey(Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='api_keys')
    key = models.CharField(max_length=80, unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    @classmethod
    def generate_key(cls):
        return secrets.token_hex(40)  # Generates an 80 character hex string

    def save(self, *args, **kwargs):
        if not self.key:
            self.key = self.generate_key()
        return super().save(*args, **kwargs)

    def __str__(self):
        return f"API Key for {self.user.username}"


@app.route("/")
def status(request):
    return "OK"

@app.api.post("/add")
def post_data(request: HttpRequest):
    apikey = request.headers["Authorization"]
    key = APIKey.objects.get(key=apikey)
    if not key:
        return {"error": "Invalid API Key"}
    print(request.body)
    return {"status": "ok"}

However, when I run it I stumble on this issue:

Traceback (most recent call last):
  File "/Users/vincent/.local/share/uv/python/cpython-3.10.14-macos-aarch64-none/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Users/vincent/.local/share/uv/python/cpython-3.10.14-macos-aarch64-none/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/nanodjango/__main__.py", line 5, in <module>
    invoke()
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/nanodjango/commands.py", line 129, in invoke
    cli(obj={})
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 1686, in invoke
    sub_ctx = cmd.make_context(cmd_name, args, parent=ctx)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 943, in make_context
    self.parse_args(ctx, args)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 1408, in parse_args
    value, args = param.handle_parse_result(ctx, opts, args)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 2400, in handle_parse_result
    value = self.process_value(ctx, value)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/click/core.py", line 2362, in process_value
    value = self.callback(ctx, self, value)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/nanodjango/commands.py", line 31, in load_app
    module = load_module(path.stem, path)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/nanodjango/commands.py", line 13, in load_module
    module = SourceFileLoader(module_name, str(path)).load_module()
  File "<frozen importlib._bootstrap_external>", line 548, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1063, in load_module
  File "<frozen importlib._bootstrap_external>", line 888, in load_module
  File "<frozen importlib._bootstrap>", line 290, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 719, in _load
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/vincent/Development/koaning-io-mkdocs/demo.py", line 5, in <module>
    from django.contrib.auth.models import User
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/contrib/auth/models.py", line 5, in <module>
    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/contrib/auth/base_user.py", line 40, in <module>
    class AbstractBaseUser(models.Model):
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/db/models/base.py", line 129, in __new__
    app_config = apps.get_containing_app_config(module)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/apps/registry.py", line 260, in get_containing_app_config
    self.check_apps_ready()
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/apps/registry.py", line 137, in check_apps_ready
    settings.INSTALLED_APPS
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/conf/__init__.py", line 81, in __getattr__
    self._setup(name)
  File "/Users/vincent/Development/koaning-io-mkdocs/.venv/lib/python3.10/site-packages/django/conf/__init__.py", line 61, in _setup
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.

When I remove the user key on the APIKey object and also remove the associated import then it does seem to work though.

@radiac
Copy link
Owner

radiac commented Oct 1, 2024

I think this is related to the import order issue mentioned in troubleshooting - I should update that to be clearer.

Django doesn't like us putting everything in one file, so nanodjango has to use some trickery to get models to work. This is applied when you do Django() - so if you move your app = up to line 3 it should work. This limitation is not great - I've just opened #37 to try to improve the situation.

However, in this specific case you could probably remove the import User and use models.ForeignKey(app.settings.AUTH_USER_MODEL, ..., as that will be deferred.

@renanmoretto
Copy link

hey

not the same error but related

i'm trying to configure a nanodjango app with custom user so i can use django login/logout/auth stuff with my custom model, but cant make it work

here is the code:

import uuid
from pathlib import Path

from nanodjango import Django
from django.shortcuts import render
from django.db import models
from django.utils import timezone


from decouple import config
from dotenv import load_dotenv

load_dotenv()


BASE_DIR = Path(__file__).resolve().parent
DB_DIR = BASE_DIR / "db"
DEBUG = config("DEBUG", cast=bool)
SECRET_KEY = config("SECRET_KEY")


app = Django(
    SECRET_KEY=SECRET_KEY,
    DEBUG=DEBUG,
    ADMIN_URL="admin/",
    AUTH_USER_MODEL="???.User",
    DATABASES={
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": DB_DIR / "db.sqlite3",
            "OPTIONS": {
                "init_command": "PRAGMA journal_mode=WAL;PRAGMA synchronous=NORMAL;",
                "transaction_mode": "IMMEDIATE",
            },
        }
    },
    STATICFILES_DIRS=[
        BASE_DIR / "static",
    ],
    AUTH_PASSWORD_VALIDATORS=[],
)

# This needs to be imported after the Django app is created
from django.contrib.auth.models import (
    AbstractBaseUser,
    PermissionsMixin,
)


class User(AbstractBaseUser, PermissionsMixin):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    email = models.EmailField(unique=True)
    password = models.CharField(max_length=128)
    datetime_joined = models.DateTimeField(default=timezone.now)
    last_login = models.DateTimeField(blank=True, null=True)
    is_active = models.BooleanField(default=True)
    is_superuser = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    verified_email = models.BooleanField(default=False)
    full_name = models.CharField(max_length=255, blank=True, null=True)
    birth_date = models.DateField(blank=True, null=True)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = []

    class Meta:
        db_table = "users"


@app.route("/")
def home_view(request):
    return render(request, "home.html")


if __name__ == "__main__":
    app.run()

i wrote ???.User because i dont know what to write for the app
do I need to make an app for it? does nanodjango has a default app for its models? i tried something like app.User but didnt work

@radiac
Copy link
Owner

radiac commented Nov 26, 2024

Nanodjango uses the filename as the name of the app, so if your file is counter.py, your user model there would be counter.User.

Hope that helps!

@renanmoretto
Copy link

Nanodjango uses the filename as the name of the app, so if your file is counter.py, your user model there would be counter.User.

Hope that helps!

hey!

my file is app.py so i wrote AUTH_USER_MODEL="app.User"

getting this error:
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'app.User' that has not been installed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Ready
Development

No branches or pull requests

3 participants