FieldError — Unknown field(s): django-fluent-contents - django

I'm a Python/Django noob. So any help will be appreciated.
Trying to use the django-fluent-contents
models.py
from django.core.urlresolvers import reverse
from django.db import models
from fluent_contents.models.fields import PlaceholderField, PlaceholderRelation, ContentItemRelation
from fluent_contents.models import ContentItem
class Article(models.Model):
title = models.CharField("Title", max_length=200)
slug = models.SlugField("Slug", unique=True)
content = PlaceholderField("article_content")
placeholder_set = PlaceholderRelation()
contentitem_set = ContentItemRelation()
class Meta:
verbose_name = "Article"
verbose_name_plural = "Articles"
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('article-details', kwargs={'slug': self.slug})
admin.py
from django.contrib import admin
from article.models import Article
from fluent_contents.admin import PlaceholderFieldAdmin
class ArticleAdmin(PlaceholderFieldAdmin):
prepopulated_fields = {'slug': ('title',)}
fieldsets = (
(None, {
'fields': ('title', 'slug', ),
}),
("Contents", {
'fields': ('content',),
'classes': ('plugin-holder',),
})
)
admin.site.register(Article, ArticleAdmin)
I'm using South for migration.
db.create_table(u'article_article', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('title', self.gf('django.db.models.fields.CharField')(max_length=200)),
('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=50)),
))
db.send_create_signal(u'article', ['Article'])
It looks like, no column is being created for the 'content' field.
So when I try to add a new 'Article' via django admin —
FieldError at /manage/article/article/add/
Unknown field(s) (content) specified for Article. Check fields/fieldsets/exclude attributes of class ArticleAdmin.
If I remove the fieldset from admin.py
class ArticleAdmin(PlaceholderFieldAdmin):
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Article, ArticleAdmin)
The 'content' field is not shown in django admin
In reply to #vdboor.. Here's my installed apps ...
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
# 3rd party apps
'south',
'django_extensions',
'compressor',
'debug_toolbar',
'fluent_contents',
'fluent_contents.plugins.text',
'django_wysiwyg',
# Project specific apps go here
'article',
)
Also I'm using the example app from the repo as a guide... just removed the extra plugin model
FYI I'm using
Django==1.6
MySQL-python==1.2.4
South==0.8.4
Thank you for all the help :-)

It looks like, no column is being created for the 'content' field.
That is correct, the PlaceholderField becomes a reverse-generic-relation.
You can try removing the fieldsets declaration for now, and see what other error you get.
The repository also contains an example application, which you can run, and compare with your app.
Silly question, but is fluent_contents in the INSTALLED_APPS?

Still need to add extra fields. In the example shown, because the content is stored in a separate table - model ContentItem.
from fluent_contents.models.fields import PlaceholderField, PlaceholderRelation, ContentItemRelation
class Article(models.Model):
title = models.CharField("Title", max_length=200)
slug = models.SlugField("Slug", unique=True)
content = PlaceholderField("article_content")
placeholder_set = PlaceholderRelation() # <-- this
contentitem_set = ContentItemRelation() # <-- and this
class Meta:
verbose_name = "Article"
verbose_name_plural = "Articles"

Related

django-tenants: Restrict access to public schema

I am trying to create a multi tenant app (with shared database and isolated schema) using this Django-Tenants package.
And I've followed the example videos to setup a demo: video1 and video2
app clients (models.py)
from django.db import models
from django_tenants.models import TenantMixin, DomainMixin
class Client(TenantMixin):
name = models.CharField("Customer name", max_length=100)
created_on = models.DateField(auto_now_add=True)
# default true, schema will be automatically created and synced when it is saved
auto_create_schema = True
class Domain(DomainMixin):
pass
app sweet_tenant (models.py)
from django.db import models
from applications.sweet_shared.models import SweetType
class Sweet(models.Model):
sweet_type = models.ForeignKey(SweetType, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
price = models.DecimalField(default=0, decimal_places=3, max_digits=8)
def __str__(self):
return self.name
app sweet_shared (models.py)
from django.db import models
class SweetType(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
settings
# Application definition
SHARED_APPS = [
"django_tenants", # mandatory
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# shared apps
"applications.clients",
"applications.sweet_shared",
]
TENANT_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# your tenant-specific apps
"applications.sweet_tenant",
)
INSTALLED_APPS = SHARED_APPS + [app for app in TENANT_APPS if app not in SHARED_APPS]
BEHAVIOUR
Public schema are shared with all tenants. Any tenant can see any data form public schema if you don't filter. This is a normal behavior
Tenants (clients) are created in the public schema.
NEEDS
I dont want that these data (tenants) can be seen by any tenant, because it will contain private client data. Each tenant only needs to see his data and only the SaaS owner can see all data (superuser in public schema).
PROBLEM
I have added this code (see code below) into the admin.py file to filter tenant's data. This works fine. But the problem is that I have not been able to detect when it is not a tenant and is the superuser of the public schema. Or is there a better way to achieve it?
from django.contrib import admin
from django_tenants.admin import TenantAdminMixin
from django.db import connection
from .models import Client
class ClientAdmin(TenantAdminMixin, admin.ModelAdmin):
list_display = (
"name",
"schema_name",
"created_on",
)
def get_readonly_fields(self, request, obj=None):
if obj: # editing an existing object
return self.readonly_fields + ('schema_name', 'created_on')
return self.readonly_fields
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.filter(name=connection.tenant)
admin.site.register(Client, ClientAdmin)
You can add the following Mixin to the ClientAdmin to only allow public tenants to see your clients and domains data.
from django.contrib import admin
from django_tenants.admin import TenantAdminMixin
from django_tenants.utils import get_public_schema_name
from backend.customers.models import Client, Domain
class PublicTenantOnlyMixin:
"""Allow Access to Public Tenant Only."""
def _only_public_tenant_access(self, request):
return True if request.tenant.schema_name == get_public_schema_name() else False
def has_view_permission(self,request, view=None):
return self._only_public_tenant_access( request)
def has_add_permission(self,request, view=None):
return self._only_public_tenant_access(request)
def has_change_permission(self,request, view=None):
return self._only_public_tenant_access( request)
def has_delete_permission(self,request, view=None):
return self._only_public_tenant_access( request)
def has_view_or_change_permission(self,request, view=None):
return self._only_public_tenant_access( request)
#admin.register(Client)
class ClientAdmin(PublicTenantOnlyMixin,TenantAdminMixin, admin.ModelAdmin):
list_display = ('name', 'paid_until')
#admin.register(Domain)
class DomainAdmin(PublicTenantOnlyMixin,TenantAdminMixin, admin.ModelAdmin):
list_display = ('domain',)

AUTH_USER_MODEL refers to model 'base.User' that has not been installed for custom auth backend

I'm trying to customize auth backend while customized auth model but keep facing this error because i'm using get_user_model() function.
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'base.User' that has not been installed
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'base.apps.BaseConfig',
'core.apps.AccountsConfig',
'system.apps.SystemConfig',
]
custom Backend:
class UserBackend(object):
def authenticate(self, request, username=None, password=None, **kwargs):
usermodel = User
try:
usr = usermodel.objects.get(username=username)
password_valid = usr.check_password(password)
if usr and password_valid:
return usr
raise PermissionDenied
except usermodel.DoesNotExist:
return PermissionDenied
return None
def get_user(self, user_id):
usermodel = User
try:
return usermodel.objects.get(pk=user_id)
except usermodel.DoesNotExist:
return None
Edit:
settings:
AUTH_USER_MODEL = 'base.User'
AUTHENTICATION_BACKENDS = (
'base.models.UserBackend',
)
base.User model:
class User(AbstractUser):
fullname = models.CharField(max_length=35, null=True, blank=True)
picture = models.ManyToManyField('ImageFile', verbose_name="ProfilePicture", blank=True)
bio = models.CharField(max_length=255, null=True, blank=True)
link = models.URLField(null=True, blank=True, default="")
is_private = models.BooleanField(default=False)
is_official = models.BooleanField(default=False)
Note: UserBackend is on the end of file and class User(AbstractUser) is above it
There was an import in base.models file, from django.contrib.auth.backends import ModelBackend which caused this error even when i removed custom AUTHENTICATION_BACKENDS.after i removed this import, everything works fine although i moved backend class from base.models to backend file in the base app (i think its not necessary, i just did it for more readable codes)
For me it was the same. It took me over an hour to find out that you cannot have the CustomBackend(BaseBackend) and the CustomUser(AbstractUser) in the models.py of your app. This info is nowhere to be found in the official Django docs.
Django Version: 3.1.2
Python Version: 3.8.2
models.py of the app "Users":
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class User(AbstractUser):
last_name = models.CharField(max_length=50)
first_name = models.CharField(max_length=50)
auth.py (arbitrary name, living in the "Users" app):
from django.db import models
from django.contrib.auth.backends import BaseBackend
class UserAuth(BaseBackend):
def authenticate(self, request, username, password):
pass
def get_user(self, user_id):
pass
settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users.apps.UsersConfig'
]
AUTH_USER_MODEL = 'users.User'
AUTHENTICATION_BACKENDS = [
'users.auth.UserAuth'
]

Object Names not displaying in Admin

Can anyone help me fix why category names are not displaying in my admin console? I am trying to use smart_selects but it seems as though something is not setup correctly. I am using django 1.9, python 2.7
Here is my models.py
from __future__ import unicode_literals
from django.db import models
from smart_selects.db_fields import ChainedForeignKey
class Category (models.Model):
category = models.CharField(max_length = 255)
def _unicode_(self):
return self.category
class Brand (models.Model):
brand = models.ForeignKey(Category)
def _unicode_(self):
return self.brand
class Make (models.Model):
category = models.ForeignKey(Category)
brand = ChainedForeignKey(Brand, chained_field = 'category',
chained_model_field = 'category', show_all = False, auto_choose = True)
Here is my admin.py
from django.contrib import admin
from .models import Category, Brand, Make
admin.site.register(Category)
admin.site.register(Brand)
admin.site.register(Make)
I have the app registered in settings
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'smart_selects',
'app',
'blog',
]
But here is how it looks in Admin console
Your function name is wrong. It's __unicode__ with 2 underscores not one.

admin.logentry: 'user' has a relation with model <class 'api.models.User'>, which has either not been installed or is abstract

django 1.5.1
I create custom auth model:
file api/models.py
from django.contrib.auth.models import BaseUserManager, AbstractUser
class User(AbstractUser):
token = models.CharField(max_length=64, null=False, blank=False, help_text=_('Photo for carte'), unique=True)
updated_token = models.DateTimeField(auto_now_add=True, help_text=_('Create record'))
USERNAME_FIELD = 'email'
objects = MyUserManager()
def __unicode__(self):
return "пользователь: %s" % self.email
class Meta:
app_label = 'custom_auth'
file settings.py
AUTH_USER_MODEL = 'custom_auth.User'
.....
INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'api',
.....
'south',
'django.contrib.admin',
)
on ./manage.py syncdb I get an error:
admin.logentry: 'user' has a relation with model <class 'api.models.User'>, which has either not been installed or is abstract.
How decide this problem?
Edit 1
tried comment line and make syncdb:
'django.contrib.admin',
syncdb was successful
after that tried create user in ./manage.py shell
In [1]: from api.models import User
In [2]: User.objects.create_superuser('test#test.com', 'test')
and recieve error:
DatabaseError: (1146, "Table 'app_name.custom_auth_user' doesn't exist")
You will need to set an app_label on your class which is also in your INSTALLED_APPS: either set app_label = 'api' (the default), or add 'custom_auth' to your INSTALLED_APPS (of course, it needs to be a valid app then).
The validation process in Django tries to get the new User class using get_model, and by default get_model returns models for installed apps only. You can verify with your current code:
>>> loading.get_model('custom_auth', 'user')
>>> loading.get_model('custom_auth', 'user', only_installed=False)
> api.models.User
You forgot to add your Meta app_label description to the INSTALLED_APPS:
# Application definition
INSTALLED_APPS = (
...
'custom_auth',
)

Django admin choice field

I have a model that has a CharField and in the admin I want to add choices to the widget. The reason for this is I'm using a proxy model and there are a bunch of models that share this CharField but they each have different choices.
class MyModel(MyBaseModel):
stuff = models.CharField('Stuff', max_length=255, default=None)
class Meta:
proxy = True
class MyModelAdmin(admin.ModelAdmin):
fields = ('stuff',)
list_display = ('stuff',)
admin.site.register(MyModel, MyModelAdmin)
For this model I want to use MY_CHOICES in MyModelAdmin.
Do I override a widget? Do I need to override the whole form?
from django.contrib import admin
from django import forms
class MyModel(MyBaseModel):
stuff = models.CharField('Stuff', max_length=255, default=None)
class Meta:
proxy = True
class MyModelForm(forms.ModelForm):
MY_CHOICES = (
('A', 'Choice A'),
('B', 'Choice B'),
)
stuff = forms.ChoiceField(choices=MY_CHOICES)
class MyModelAdmin(admin.ModelAdmin):
fields = ('stuff',)
list_display = ('stuff',)
form = MyModelForm
admin.site.register(MyModel, MyModelAdmin)
See: https://docs.djangoproject.com/en/dev/ref/forms/fields/#choicefield
You don't need a custom form.
This is the minimum you need:
# models.py
from __future__ import unicode_literals
from django.db import models
class Photo(models.Model):
CHOICES = (
('hero', 'Hero'),
('story', 'Our Story'),
)
name = models.CharField(max_length=250, null=False, choices=CHOICES)
# admin.py
from django.contrib import admin
from .models import Photo
class PhotoAdmin(admin.ModelAdmin):
list_display = ('name',)
admin.site.register(Photo, PhotoAdmin)
You can override formfield_for_choice_field() that way you don't need to create a new form.
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_choice_field(self, db_field, request, **kwargs):
if db_field.name == 'status':
kwargs['choices'] = (
('accepted', 'Accepted'),
('denied', 'Denied'),
)
if request.user.is_superuser:
kwargs['choices'] += (('ready', 'Ready for deployment'),)
return super().formfield_for_choice_field(db_field, request, **kwargs)
See formfield_for_choice_field
You need to override the form the ModelAdmin is going to use:
class MyForm(forms.ModelForm):
stuff = forms.CharField('Stuff', max_length=255, choices=MY_CHOICES, default=None)
class Meta:
model = MyModel
fields = ('stuff', 'other_field', 'another_field')
class MyModelAdmin(admin.ModelAdmin):
fields = ('stuff',)
list_display = ('stuff',)
form = MyForm
If you need your choices to be dynamic, maybe you could do something similar to:
class MyForm(forms.ModelForm):
stuff = forms.CharField('Stuff', max_length=255, choices=MY_CHOICES, default=None)
def __init__(self, stuff_choices=(), *args, **kwargs):
# receive a tupple/list for custom choices
super(MyForm, self).__init__(*args, **kwargs)
self.fields['stuff'].choices = stuff_choices
and in your ModelAdmin's __init__ define what MY_CHOICES is going to be and assign the form instance there instead:
Good luck! :)
in Gerard's answer, if you keep :
def __init__(self, stuff_choices=(), *args, **kwargs):
then when you will try to add new model from admin, you will always get 'This field is required.' for all required fields.
you should remove stuff_choices=() from initialization:
def __init__(self,*args, **kwargs):
You need to think of how you are going to store the data at a database level.
I suggest doing this:
Run this pip command: pip install django-multiselectfield
In your models.py file:
from multiselectfield import MultiSelectField
MY_CHOICES = (('item_key1', 'Item title 1.1'),
('item_key2', 'Item title 1.2'),
('item_key3', 'Item title 1.3'),
('item_key4', 'Item title 1.4'),
('item_key5', 'Item title 1.5'))
class MyModel(models.Model):
my_field = MultiSelectField(choices=MY_CHOICES)
In your settings.py:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
#.....................#
'multiselectfield',
)
Watch the MAGIC happen!
Source:
https://pypi.python.org/pypi/django-multiselectfield
Below a solution that works immediately with Postgres' special ArrayField:
# models.py
class MyModel(models.Model):
class Meta:
app_label = 'appname'
name = models.CharField(max_length=1000, blank=True)
ROLE_1 = 'r1'
ROLE_2 = 'r2'
ROLE_3 = 'r3'
ROLE_CHOICES = (
(ROLE_1, 'role 1 name'),
(ROLE_2, 'role 2 name'),
(ROLE_3, 'role 3 name'),
)
roles = ArrayField(
models.CharField(choices=ROLE_CHOICES, max_length=2, blank=True),
default=list
)
# admin.py
class MyModelForm(ModelForm):
roles = MultipleChoiceField(choices=MyModel.ROLE_CHOICES, widget=CheckboxSelectMultiple)
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
list_display = ("pk", "name", "roles")
(Django 2.2)