How to add a Model (not an app) to django? - python

I am using django 1.3 and just trying to add a simple model(not an app) to the admin site.
so i have tried:
from django.db import models
class UserProfile(models.Model):
notes = models.TextField(db_name="Notes", max_length=15)
def _str_(self):
return self.notes
class Admin:
pass
and have also tried creating the admin.py file in the site root and in the /static/admin/ directory and have attempted two standard entries for it as follows:
from django.contrib import admin
from mock.models import UserProfile
admin.site.register(UserProfile)
and
from django.contrib import admin
from mock.models import UserProfile
class UserProfileAdmin(admin.ModelAdmin):
pass
admin.site.register(UserProfile, UserProfileAdmin)
any help would be much appreciated. Thank you very much.

Don't define your Admin class in the model itself like below. That's the really old way to do it, from before Django 1.0. I'm not sure what tutorial or documentation you are using, but it's very out of date.
class UserProfile(models.Model):
notes = models.TextField(db_name="Notes", max_length=15)
# don't do this!
class Admin:
pass
Defining a UserProfileAdmin is the correct approach. The admin.py file should not go in the /static/admin/. The static directory is for static files like CSS stylesheets and javascript files, not for Django code.
As for your question of whether you can define a model without defining an app, it's not a really good idea. Lots of parts of django assume that each model belongs to an app. For example the database table name is appname_modelname.
Creating an app doesn't take too long. Run the startapp command and it will create the base directory and files.
./manage.py startapp <appname>
All you then need to do is add the new app to INSTALLED_APPS, and create your admin.py file.
As your project gets bigger, keeping models in apps will keep it more organized. Many Django users create an app named utils (or similar) for the odd model.

Related

Updates to admin.py not reflected in the django admin page

I'm building a django app and the django admin page doesn't seem to be reflecting the changes I make to admin.py. For example if I want to exclude some fields, or customizing the admin change list, nothing changes in the actual page. The only thing that seems to be reflected properly is the fact that I can register the models, and they will show up.
Here's my admin.py
from django.contrib import admin
from .models import Form, Biuletyn, Ogloszenie, Album
class FormAdmin(admin.ModelAdmin):
exclude = ('img',)
class BiuletynAdmin(admin.ModelAdmin):
list_display = ('name', 'date')
class OgloszenieAdmin(admin.ModelAdmin):
fields = ('name', 'date', 'upload')
admin.site.register(Form)
admin.site.register(Biuletyn)
admin.site.register(Ogloszenie)
admin.site.register(Album)
P.S. Please ignore the weird model names. The site is actually in a different language :D
This is how you register your ModelAdmin:
admin.site.register(Form, FormAdmin)
admin.site.register(Biuletyn, BiuletynAdmin)
admin.site.register(Ogloszenie, OgloszenieAdmin)
This how to register your Models:
admin.site.register(Album)
For more details you may refer to Django official documentation at: https://docs.djangoproject.com/en/3.2/ref/contrib/admin/#modeladmin-objects
Add admin_class
So for example for the Form model:
admin.site.register(Form, admin_class=FormAdmin)

Extending user models in Django saves password publicly

The password for newly created users is shown publicly on the admin console models. Why is that and how I do it correctly?
Furthermore, I am not actually able to login with any of the new users created in the Accounts_app. I am able to login only with the python manage.py createsuperuser
I created at the early point in the project.
Here is the models.py
from django.contrib.auth.models import AbstractUser
class ProjectUser(AbstractUser):
def __str__(self):
return self.username
Here is the settings.py
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
]
AUTH_USER_MODEL = 'accounts_app.ProjectUser'
Here is my admin view
To create the user, I click "Add User" in the app admin view.
Here is the apps.py file
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts_app'
Here is the admin.py file
from django.contrib import admin
from accounts_app.models import ProjectUser
# Register your models here.
admin.site.register(ProjectUser)
Although you set ProjectUser to be the AUTH_USER_MODEL, you registered it in the admin as a standard model, not the user one. You need to use the user admin, as shown in the docs, since this takes care of hashing the password:
from django.contrib.auth.admin import UserAdmin
admin.site.register(ProjectUser, UserAdmin)
You'll need to delete and recreate the users you generated via the admin before changing this.
Firstable, what do you want to do, extend or custom the User Model?
If you want to extend... It's enough with a foreign key. For this, the Django project recommends using OneToOneField(User)
In this case, see the link below.
https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#extending-the-existing-user-model
In the other hand, if you want to custom the User model, you must have to do this before doing the migrations. The initial setup must have your customization. You can create an app only for the User Model customization.
In this case, see the links below.
https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#substituting-a-custom-user-model
https://wsvincent.com/django-tips-custom-user-model/
I hope this helped you

How to make django admin site to not recognize a foreign key'ed model (on different app) to be a model of current app?

I have three models - two of them are in one app, and the third one is on the another. The structure is like this:
taapp.models:
class Teachers(model.Model):
fullname = models.CharField(max_length=50)
...
class TeachersScale(model.Model):
teacher = models.ForeignKey("Teachers")
abbr = models.ForeignKey("questions.QuestionTypes")
questions.models:
class QuestionTypes(models.Model):
abbr = models.CharField(max_length=5)
......
I registered all these models to admin:
taapp.admin:
from taapp.models import Teachers
from taapp.models import TeachersScale
from django.contrib import admin
from admin_forms import TeachersAdmin, TeachersScaleAdmin
admin.site.register(Teachers, TeachersAdmin)
admin.site.register(TeachersScale, TeachersScaleAdmin)
taapp.admin_forms:
from django import forms
from django.contrib import admin
class TeachersAdmin(admin.ModelAdmin):
list_display = ('fullname', 'email', 'registration_date')
class TeachersScaleAdmin(admin.ModelAdmin):
list_display = ('teacher', 'abbr')
list_filter = ['teacher','abbr']
When I try to add a field to TeachersScale in admin site, I get the following error:
DatabaseError at /admin/taapp/teachersscale/add/
(1146, "Table 'taapp.questions_questiontypes' doesn't exist")
It treats QuestionTypes, as it is a model in taapp. How to solve it? Or is there something wrong with my db design?
I tried TabularInline for QuestionTypes to see if reverse adding works. Well, it works:
questions.admin:
class TeachersScaleInline(admin.TabularInline):
model = TeachersScale
class QuestionTypesAdmin(admin.ModelAdmin):
inlines = [TeachersScaleInline]
Thanks in advance.
It looks like you haven't actually created your questions table, or if you have you've forced it into a different database. Foreign keys expect to share the same database, and it's perfectly standard to have multiple apps sharing the same database. That's why the app name is part of the automatically generated table name.

Where do I create custom profile models for django-userena?

I have a django app called my_app that uses django-userena; I am trying to create and use my own profile model by following the django-userena installation documentation.
In my_app/models.py I've added
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from userena.models import UserenaBaseProfile
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User,
unique=True,
verbose_name=_('user'),
related_name='my_profile')
favourite_snack = models.CharField(_('favourite snack'),
max_length=5)
And then I've modified my_app/settings.py to include AUTH_PROFILE_MODULE = 'my_app.MyProfile' .
And yet, when I try to view any web page from my_app I get a SiteProfileNotAvailable. This error goes away if I move MyProfile to accounts/models.py
It seems like a bad idea to modify the accounts app in order to add custom fields. Am I wrong? Is there a way to add a custom profile module without modifying accounts/models.py?
I had the same issue. For me it happened because I forgot to put my_app (or accounts as in the official docs) into INSTALLED_APPS.

Mixin Field into Existing and uneditable django model

I would like to mix a field into an existing model which I would rather not edit (it comes from a third party project and I would rather leave the project untouched). I have created a simple example which illustrates what I am trying but unable to do:
In an empty Django project I have created apps app1 and app2 (they are in that order in settings). They look like the following:
app1.models.py:
from django.db import models
from app2.models import BlogPost
class BlogPostExtend(models.Model):
custom_field_name = models.CharField(max_length=200)
class Meta:
abstract = True
BlogPost.__bases__ = (BlogPostExtend,)+BlogPost.__bases__ # this prevents MRO error
app2.models.py:
from django.db import models
class BlogPost(models.Model):
field_name = models.CharField(max_length=100)
Unfortunately this does not result in custom_field_name being created in the database when I syncdb, although at the command line if I type BlogPost.custom_field_name it does recognize it as a CharField. I know that in this simple case I could have BlogPost inherit from BlogPostExtend, but in the real use case I cannot edit BlogPost.
This is a very simplified example but it illustrates what I am trying to do.
Thanks!
Mixins work great with adding attributes and methods, but not fields.
In app1.models.py, do this instead:
from django.db import models
from app2.models import BlogPost
custom_field_name = models.CharField(max_length=200)
custom_field_name.contribute_to_class(BlogPost, "custom_field_name")
I think also the app1 app should come after app2 in INSTALLED_APPS for this to work.
Here is an explanation on contribute_to_class

Categories