I am working thru the Practical Django Projects book and am stumped. The book is for an earlier version of Django. I am using v1.3.
The problem is in the view, at 'search_keyword_keyword__in...'
from django.contrib.flatpages.models import FlatPage
from django.shortcuts import render_to_response
def search(request):
query = request.GET.get('q', '')
keyword_results = results = []
if query:
keyword_results = FlatPage.objects.filter(searchkeyword__keyword__in=query.split()).distinct()
results = FlatPage.objects.filter(content__icontains=query)
return render_to_response('search/search.html',
{'query' : query,
'keyword_results': keyword_results,
'results' : results })
The models.py is
from django.contrib.flatpages.models import FlatPage
from django.db import models
class SearchKeyword(models.Model):
keyword = models.CharField(max_length=50)
page = models.ForeignKey(FlatPage)
def __unicode__(self):
return self.keyword
The full error is:
Cannot resolve keyword 'searchkeyword' into field. Choices are: content, enable_comments, id, registration_required, sites, template_name, title, url
Which I think are the options for FlatPages. It doesn't seem like the foreign key relationship is being found.
Any ideas what could be wrong or how to correctly do the lookup? Thanks.
Here is the admin.py in case it has some bearing:
from django.contrib.flatpages.admin import FlatPageAdmin
from django.contrib import admin
from cms.search.models import SearchKeyword
from django.contrib.flatpages.models import FlatPage
# Define an inline admin descriptor for SearchKeywords model
class SearchKeywordInline(admin.TabularInline):
model = SearchKeyword
# Define a FlatPageAdmin class
class ExtendedFlatPageAdmin(FlatPageAdmin):
inlines = [
SearchKeywordInline,
]
# Re-register FlatPageAdmin
admin.site.unregister(FlatPage)
admin.site.register(FlatPage, ExtendedFlatPageAdmin)
The reverse relationship for your ForeignKey would be named searchkeyword_set (see https://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects), so your queryset should have searchkeyword_set__keyword__in as a a parameter (or you can use related_name.
If that didn't work, you should check that you have done manage.py syncdb ?
It seems the problem was:
from django.contrib.flatpages.models import FlatPage
from django.db import models
The models needs to come first, like:
from django.db import models
from django.contrib.flatpages.models import FlatPage
I think what was happening is the FlatPage instance was being created before the ForeignKey was created, therefore the SearchKeyword attribute was not available to FlatPage.
Related
I am trying to intregrate django-summernote in my blog post admin area.
when I set summernote_fields = ('description',) and register to admin area, I am getting error like below :
for model in model_or_iterable:
TypeError: 'MediaDefiningClass' object is not iterable
My admin.py is given below :
from django.contrib import admin
from django_summernote.admin import SummernoteModelAdmin
from .models import Blog
class BlogPostSummerNote(SummernoteModelAdmin):
summernote_fields = ('description',)
#admin.register(Blog)
class BlogAdmin(admin.ModelAdmin):
list_display = ('title','slug','author','publish','status')
prepopulated_fields = {'slug':('title',)}
admin.site.register(BlogPostSummerNote)
I can't able to figure this out . Can any one tell me why this is happening ??
############# SOLUTION #################
I Solved this problem by doing as below in admin.py:
from django.contrib import admin
from django_summernote.admin import SummernoteModelAdmin
from .models import Blog
#admin.register(Blog)
class BlogPostSummerNote(SummernoteModelAdmin):
list_display = ('title','slug','author','publish','status')
summernote_fields = ('description',)
prepopulated_fields = {'slug':('title',)}
Hi have been working with Django and i want to have relations bettwen model i have the following structure
on posts/models.py
from django.db import models
class Post(models.Model):
(SKIP ATTRIBUTES)
and then on comments/model.py
from django.db import models
from posts.models import Post
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments')
In a nutshell im trying to import posts model into comment model and i get the error that
cannot import name 'Post' from 'posts.models , how should import posts model to avoid this issue ?
from posts.models import Post
ImportError: cannot import name 'Post' from 'posts.models
If you are also importing comments.models in posts.models,
This may happen due to circular import. Try this:
from posts import models as posts_models
and
post = models.ForeignKey(posts_models.Post,on_delete=models.CASCADE,related_name='comments')
Try this, tell me if it helps
from DjangoPost.posts.models import Post
instead of
from posts.models import Post
I'm trying to customise my Django admin page. I want a single model field to render all the choices passed to it as a CheckboxSelectMultiple, but can't get it to work.
Here is the relevant part of my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
class Event(models.Model):
GROUP_OWNER_CHOICES = (
('vcoe', "VCOE"),
('cssi', 'CSSI'),
('essc', "ESSC"),
('tmscc', "TMSCC"),
('inmc', "INMC"),
('ccs7', "CCS7"),
('ias', "IAS"),
)
group_owner = models.BooleanField(choices=GROUP_OWNER_CHOICES, blank=True, default=False)
I can't use the Django formfield_overrides(https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form) because I have more than 1 BooleanField and would like to keep the other BooleanField's intact.
Here is what I found from other questions
from django.contrib import admin
from .models import Event
from django import forms
class EventGroupOwnerAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(EventGroupOwnerAdminForm, self).__init__(*args,**kwargs)
self.fields["group_owner"].widget = forms.widgets.CheckboxSelectMultiple()
class EventAdmin(admin.ModelAdmin):
form = EventGroupOwnerAdminForm
admin.site.register(Event , EventAdmin)
But the field simply doesnt render anything. Any help?
If I want to register my models with the admin I have to do this like this:
#admin.py
admin.site.register(models.About)
But with multiple models you can't do something like this:
models = (models.Project, models.Client, models.About)
for m in models:
admin.site.register(m)
First of all: why not!? Secondly: imagine one has a lot of models which all should be accessible from the admin interface. How do you do that in a generic way?
admin.site.register has this definition in the library:
def register(self, model_or_iterable, admin_class=None, **options):
so models to be registered can be a single model or iterable object so just use this:
myModels = [models.Project, models.Client, models.About] # iterable list
admin.site.register(myModels)
I tested this in my site and works perfectly fine.
# File: admin.py
from django.contrib import admin
from .models import Project, Client, About
admin.register(Project, Client, About)(admin.ModelAdmin)
With respect to the recent release of Django 1.7, you can use the django.contrib.admin.register decorator to register multiple models that using the same admin class.
from django.contrib import admin
from .models import Project, Client, About
#admin.register(Project, Client, About)
class DefaultAdmin(admin.ModelAdmin):
pass
Update
Consider making a simple call instead of declaring a dummy class
Based on the snippet here, what I usually do is have the following code in my admin.py
from django.db.models import get_models, get_app
from django.contrib import admin
from django.contrib.admin.sites import AlreadyRegistered
def autoregister(*app_list):
for app_name in app_list:
app_models = get_app(app_name)
for model in get_models(app_models):
try:
admin.site.register(model)
except AlreadyRegistered:
pass
autoregister('myapp')
With Django 3.1.3
in admin.py
from .models import Course, Category
admin.site.register(Course)
admin.site.register(Category)
This is better way to regestering multiple models
from django.contrib import admin
from myapp.models import Course, Category
admin.site.register(Course)
admin.site.register(Category)
from django.contrib import admin
from .models import *
#admin.register(Project, Client, About)
class AppAdmin(admin.ModelAdmin):
pass
Here is a wrokaround that attempts to register a custom models to the admin UI if existing else the default one, for that to work, you must follow the convention of naming your custom admin classes as "MyModelAdmin" by appending "Admin" to the end.
for model_name, model in apps.get_app_config('myapp').models.items() :
if '_' not in model_name :
if globals().get(model.__name__+'Admin') :
admin.site.register(model, globals().get(model.__name__+'Admin'))
else :
admin.site.register(model)
-> if you have just one model:
from django.contrib import admin
from .models import MyModel1
class myModel1Admin(admin.ModelAdmin):
list_display = ("name", "address")
admin.site.register(MyModel1, myModel1Admin)
-> but if you have more than one model or ModelAdmin, you can register them separately:
e.g:
from django.contrib import admin
from .models import MyModel1, MyModel2
class myModel1Admin(admin.ModelAdmin):
list_display = ("name", "address")
class myModel2Admin(admin.ModelAdmin):
list_display = ("name", "photo")
admin.site.register(MyModel1, myModel1Admin)
admin.site.register(MyModel2, myModel2Admin)
I have an app named doors and my models.py for the app has 10 tables/class. Under my admin.py, how do I register every model in the file models.py?
For example, currently I have to hardcode it:
from django.contrib import admin
from doors.models import *
admin.site.register(Group)
admin.site.register(Item)
admin.site.register(ItemType)
admin.site.register(Location)
admin.site.register(Log)
admin.site.register(Order)
admin.site.register(Property)
admin.site.register(User)
admin.site.register(Vendor)
Is there a way I perhaps find every class in models.py and loop through and register each class? Or is there some kind of wildcard I can use with Django?
Seems get_models and get_app are no longer available in django 1.8.
The following can be used:
from django.contrib import admin
from django.apps import apps
app = apps.get_app_config('dashboard')
for model_name, model in app.models.items():
admin.site.register(model)
EXTENSION: If you would like to show all or select fields of the model as a grid instead of a single column unicode representation of the model objects you may use this:
app = apps.get_app_config('your_app_name')
for model_name, model in app.models.items():
model_admin = type(model_name + "Admin", (admin.ModelAdmin,), {})
model_admin.list_display = model.admin_list_display if hasattr(model, 'admin_list_display') else tuple([field.name for field in model._meta.fields])
model_admin.list_filter = model.admin_list_filter if hasattr(model, 'admin_list_filter') else model_admin.list_display
model_admin.list_display_links = model.admin_list_display_links if hasattr(model, 'admin_list_display_links') else ()
model_admin.list_editable = model.admin_list_editable if hasattr(model, 'admin_list_editable') else ()
model_admin.search_fields = model.admin_search_fields if hasattr(model, 'admin_search_fields') else ()
admin.site.register(model, model_admin)
What this does is, it extends ModelAdmin class on the fly and sets the list_display field which is required for showing model data in grid representation in the admin. If you list your desired fields in your model as admin_list_display it takes that one, or generates a tuple of all fields available in the model, otherwise.
Other optional fields can similarly be set, such as list_filter.
See django documentation for more info on list_display.
I figured it out with #arie's link (for django < 1.8):
from django.contrib import admin
from django.db.models import get_models, get_app
for model in get_models(get_app('doors')):
admin.site.register(model)
But I wonder if I can do this without get_app... Couldn't the code be smart enough to know the name of its own app?
From Django 1.7 on, you can use this code in your admin.py:
from django.apps import apps
from django.contrib import admin
from django.contrib.admin.sites import AlreadyRegistered
app_models = apps.get_app_config('my_app').get_models()
for model in app_models:
try:
admin.site.register(model)
except AlreadyRegistered:
pass
From Django 1.8, to fix the error message
RemovedInDjango19Warning: django.db.models.get_app is deprecated.
We can use this approach in 2 lines
from django.contrib import admin
from my_app.models import *
from django.apps import apps
for model in apps.get_app_config('my_app').models.values():
admin.site.register(model)
from django.apps import apps
from django.contrib.admin.sites import AlreadyRegistered
app_models = apps.get_app_config('app-name').get_models()
for model in app_models:
try:
admin.site.register(model)
except AlreadyRegistered:
pass
from django.contrib import admin
from .models import Projects, ProjectsUsers, Comments, ProjectsDescription
Models = (Projects, ProjectsUsers, Comments, ProjectsDescription)
admin.site.register(Models)
From Django3.0,you can try add the following code in admin.py
from . import models
class ListAdminMixin(object):
def __init__(self, model, admin_site):
self.list_display = [field.name for field in model._meta.fields if field.name != "id"]
super(ListAdminMixin, self).__init__(model, admin_site)
for m in [your_model_name]:
mod = getattr(models, m)
admin_class = type('AdminClass', (ListAdminMixin, admin.ModelAdmin), {})
try:
admin.site.register(mod, admin_class)
except admin.sites.AlreadyRegistered:
pass