Django +2 ImportError: cannot import model - django

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

Related

Import and register all classes from models in admin-django

In myApp, I have multiple classes in models. I would like to import all of these classes in admin.py and register.
Is it possible without repetition such as
from django.contrib import admin
from .models import (classA,classB, classC)
Could I import all the items without explicitly referring as done above
Could I also register all at one time
Thanks
Jeff
You can try this :-
import inspect
import models
for name, obj in inspect.getmembers(models):
if inspect.isclass(obj):
admin.site.register(obj)
This will get all the class of models.py and register on admin under loop.
I have not try it but its work same for getting classes on python.
you can register all model by using this:
from django.db.models.base import ModelBase
from django.contrib import admin
import models
for model_name in dir(models):
model = getattr(models, model_name)
if isinstance(model, ModelBase):
admin.site.register(model)

django google maps

I'm new in django. I need a google map in my model.
1. I tried to use django-google-maps.my models.py is:
from django.db import models
from django_google_maps import fields as map_fields
class Rental(models.Model):
address = map_fields.AddressField(max_length=200)
geolocation = map_fields.GeoLocationField(max_length=200)
and my admin.py:
from django.contrib import admin
from django_google_maps import widgets as map_widgets
from django_google_maps import fields as map_fields
from .models import Rental
class RentalAdmin(admin.ModelAdmin):
formfield_overrides = {
map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
}
admin.site.register(Rental, RentalAdmin)
but when i click on the map in admin interface that fields are still empty .
I used this guide to install it https://github.com/madisona/django-google-maps
2.I tried to use easy-map by this guide http://pypi.python.org/pypi/django-easy-maps but I can't see address preview in admin interface.
my admin.py is:
from django import forms
from django.contrib import admin
from easy_maps.widgets import AddressWithMapWidget
from .models import Address
class AddressAdmin(admin.ModelAdmin):
class form(forms.ModelForm):
class Meta:
widgets = {
'address': AddressWithMapWidget({'class': 'vTextField'})
}
admin.site.register(Address, AddressAdmin)
You might be missing Google API Key in settings.py
GOOGLE_MAPS_API_KEY = 'your key here'
generate your Google Maps Javascript API from https://code.google.com/apis/console.

How to register multiple models with the admin?

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)

Register every table/class from an app in the Django admin page

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

django FieldError at /search/ Cannot resolve keyword 'searchkeyword'

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.