Django: NameError 'Business' is not defined - django

Not sure what is causing this error. Please help
NameError at /dash/
name 'Business' is not defined
Exception Location: /home/src/common/models.py in ImageBank, line 38
Here's the model:
class Business(models.Model):
business_type = models.ManyToManyField(BusinessType)
business_service_type = models.ManyToManyField(ServiceType)
establishment_type = models.ForeignKey(EstablishmentType)
logo = models.ForeignKey(ImageBank)
phone = PhoneNumberField()
address = models.ForeignKey(Address)
website = models.URLField()
name = models.CharField(max_length=64)
def __unicode__(self):
return self.name
The View:
def dashview(request):
coupon = Coupon.objects.filter()
bdnspk = request.user.id
user = request.user.username
bdns = Business.objects.values('name').get(id=bdnspk)
context = {
'coupon':coupon,
'bdns':bdns,
'user':user
}
return render_to_response(
'dash/dash.html',
{},
context,
context_instance = RequestContext(request),
)
EDIT: my models is located in /home/src/common/models.py but my django app is in /home/proj/site/ How do I import that?
ImageBank model:
class ImageBank(models.Model):
business = models.ForeignKey('Business')
image = models.ImageField(upload_to="images/bank")
def url(self):
return self.image.url

Please look at your error: Exception Location: /home/src/common/models.py in ImageBank, line 38 the problem exists in the ImageBank class, which you also seem to be using a ForeignKey reference to in the logo field.
I'm assuming that what the issue is is that you are referencing Business before it is defined as something like a ForeignKey reference inside a field in ImageBank. If this is the case, is ImageBank defined before the Business model inside your models.py? Because doing so will throw this error. The proper way of doing circular ForeignKey references would be to enforce a single ForeignKey with a unique constraint.
Django has this concept built in as a type of field called a OnetoOne field. Have you looked into using a OnetoOne field? See: http://docs.djangoproject.com/en/dev/ref/models/fields/#onetoonefield

Did you import the models in the view? Something like:
from models import Business
at the beginning of the view file

You forgot to import the model in the view, or you're referring to it incorrectly.

If that model is in an app you wrote:
Make sure that the app is listed in INSTALLED_APPS in your settings.py
#settings.py
INSTALLED_APPS = (
'django....',
... more defaults ...,
'myproject.appname',
)
and at the top of your views
#views.py
from appname.models import Business
#or import all models from that app
from appname.models import *

You are making things a lot more complicated on yourself by having your models.py in a strange unrelated location.
Models can only be imported from python modules so you'll need to make sure that your models.py is in a directory that is a python module and that it is on the python path.
You'll be a whole lot better of just putting your models into an app in your project rather than trying to do something like you are.
More or less you're working against the grain and python is a lot nicer if you work with the grain.

Related

Save django CreateView in Python Shell

I'm trying to write a test for my CreateView view in django. As part fo the test, I want to create a new object through a CreateView class, though I'm unsure how to save the object through tests.py.
models.py
class MyModel(models.Model):
name = models.CharField(
max_length = 50,
)
views.py
class MyCreateView(CreateView):
model = MyModel
tests.py
from myapp.views import MyCreateView
m = MyCreateView()
m.name = 'John Doe'
# save object here
Neither m.save() nor m.submit() will work. Any suggestions?
Please refer to Django docs: https://docs.djangoproject.com/en/4.0/topics/testing/
It is well documented and shows how to test views and models.

How to change THIS specific text output in django admin? [duplicate]

In the same way that you can give fields and models verbose names that appear in the Django admin, can you give an app a custom name?
Django 1.8+
Per the 1.8 docs (and current docs),
New applications should avoid default_app_config. Instead they should require the dotted path to the appropriate AppConfig subclass to be configured explicitly in INSTALLED_APPS.
Example:
INSTALLED_APPS = [
# ...snip...
'yourapp.apps.YourAppConfig',
]
Then alter your AppConfig as listed below.
Django 1.7
As stated by rhunwicks' comment to OP, this is now possible out of the box since Django 1.7
Taken from the docs:
# in yourapp/apps.py
from django.apps import AppConfig
class YourAppConfig(AppConfig):
name = 'yourapp'
verbose_name = 'Fancy Title'
then set the default_app_config variable to YourAppConfig
# in yourapp/__init__.py
default_app_config = 'yourapp.apps.YourAppConfig'
Prior to Django 1.7
You can give your application a custom name by defining app_label in your model definition. But as django builds the admin page it will hash models by their app_label, so if you want them to appear in one application, you have to define this name in all models of your application.
class MyModel(models.Model):
pass
class Meta:
app_label = 'My APP name'
As stated by rhunwicks' comment to OP, this is now possible out of the box since Django 1.7
Taken from the docs:
# in yourapp/apps.py
from django.apps import AppConfig
class YourAppConfig(AppConfig):
name = 'yourapp'
verbose_name = 'Fancy Title'
then set the default_app_config variable to YourAppConfig
# in yourapp/__init__.py
default_app_config = 'yourapp.apps.YourAppConfig'
If you have more than one model in the app just create a model with the Meta information and create subclasses of that class for all your models.
class MyAppModel(models.Model):
class Meta:
app_label = 'My App Label'
abstract = True
class Category(MyAppModel):
name = models.CharField(max_length=50)
Well I started an app called todo and have now decided I want it to be named Tasks. The problem is that I already have data within my table so my work around was as follows. Placed into the models.py:
class Meta:
app_label = 'Tasks'
db_table = 'mytodo_todo'
Hope it helps.
Give them a verbose_name property.
Don't get your hopes up. You will also need to copy the index view from django.contrib.admin.sites into your own ProjectAdminSite view and include it in your own custom admin instance:
class ProjectAdminSite(AdminSite):
def index(self, request, extra_context=None):
copied stuff here...
admin.site = ProjectAdminSite()
then tweak the copied view so that it uses your verbose_name property as the label for the app.
I did it by adding something a bit like this to the copied view:
try:
app_name = model_admin.verbose_name
except AttributeError:
app_name = app_label
While you are tweaking the index view why not add an 'order' property too.
First you need to create a apps.py file like this on your appfolder:
# appName/apps.py
# -*- coding: utf-8 -*-
from django.apps import AppConfig
class AppNameConfig(AppConfig):
name = 'appName'
verbose_name = "app Custom Name"
To load this AppConfig subclass by default:
# appName/__init__.py
default_app_config = 'appName.apps.AppNameConfig'
Is the best way to do. tested on Django 1.7
For the person who had problems with the Spanish
This code enable the utf-8 compatibility on python2 scripts
# -*- coding: utf-8 -*-
For Django 1.4 (not yet released, but trunk is pretty stable), you can use the following method. It relies on the fact that AdminSite now returns a TemplateResponse, which you can alter before it is rendered.
Here, we do a small bit of monkey patching to insert our behaviour, which can be avoided if you use a custom AdminSite subclass.
from functools import wraps
def rename_app_list(func):
m = {'Sites': 'Web sites',
'Your_app_label': 'Nicer app label',
}
#wraps(func)
def _wrapper(*args, **kwargs):
response = func(*args, **kwargs)
app_list = response.context_data.get('app_list')
if app_list is not None:
for a in app_list:
name = a['name']
a['name'] = m.get(name, name)
title = response.context_data.get('title')
if title is not None:
app_label = title.split(' ')[0]
if app_label in m:
response.context_data['title'] = "%s administration" % m[app_label]
return response
return _wrapper
admin.site.__class__.index = rename_app_list(admin.site.__class__.index)
admin.site.__class__.app_index = rename_app_list(admin.site.__class__.app_index)
This fixes the index and the app_index views. It doesn't fix the bread crumbs in all other admin views.
No, but you can copy admin template and define app name there.
There is a hack that can be done that does not require any migrations.
Taken from Ionel's blog and credit goes to him: http://blog.ionelmc.ro/2011/06/24/custom-app-names-in-the-django-admin/
There is also a ticket for this that should be fixed in Django 1.7 https://code.djangoproject.com/ticket/3591
"""
Suppose you have a model like this:
class Stuff(models.Model):
class Meta:
verbose_name = u'The stuff'
verbose_name_plural = u'The bunch of stuff'
You have verbose_name, however you want to customise app_label too for different display in admin. Unfortunatelly having some arbitrary string (with spaces) doesn't work and it's not for display anyway.
Turns out that the admin uses app_label. title () for display so we can make a little hack: str subclass with overriden title method:
class string_with_title(str):
def __new__(cls, value, title):
instance = str.__new__(cls, value)
instance._title = title
return instance
def title(self):
return self._title
__copy__ = lambda self: self
__deepcopy__ = lambda self, memodict: self
Now we can have the model like this:
class Stuff(models.Model):
class Meta:
app_label = string_with_title("stuffapp", "The stuff box")
# 'stuffapp' is the name of the django app
verbose_name = 'The stuff'
verbose_name_plural = 'The bunch of stuff'
and the admin will show "The stuff box" as the app name.
"""
If you already have existing tables using the old app name, and you don't want to migrate them, then just set the app_label on a proxy of the original model.
class MyOldModel(models.Model):
pass
class MyNewModel(MyOldModel):
class Meta:
proxy = True
app_label = 'New APP name'
verbose_name = MyOldModel._meta.verbose_name
Then you just have to change this in your admin.py:
#admin.site.register(MyOldModel, MyOldModelAdmin)
admin.site.register(MyNewModel, MyOldModelAdmin)
Be aware that the url will be /admin/NewAPPname/mynewmodel/ so you might just want to make sure that the class name for the new model looks as close to the old model as possible.
Well, this works for me. In the app.py use this:
class MainConfig(AppConfig):
name = 'main'
verbose_name="Fancy Title"
In setting.py add the name of App and the class name present in app.py file in App folder
INSTALLED_APPS = [
'main.apps.MainConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
That's simple just add as follow on your appName/apps
class AppNameConfig(AppConfig):
default_auto_field = 'default Django'
name = 'AppName'
verbose_name = 'Name you Want'
The following plug-and-play piece of code works perfectly since Django 1.7. All you have to do is copy the below code in the __init__.py file of the specific app and change the VERBOSE_APP_NAME parameter.
from os import path
from django.apps import AppConfig
VERBOSE_APP_NAME = "YOUR VERBOSE APP NAME HERE"
def get_current_app_name(file):
return path.dirname(file).replace('\\', '/').split('/')[-1]
class AppVerboseNameConfig(AppConfig):
name = get_current_app_name(__file__)
verbose_name = VERBOSE_APP_NAME
default_app_config = get_current_app_name(__file__) + '.__init__.AppVerboseNameConfig'
If you use this for multiple apps, you should factor out the get_current_app_name function to a helper file.
Update for 2021 (Django 3.2):
Inside the app.py file of your App you find the AppClientsConfig class. Inside you find the name attribute. Don't change that unless you really have to (and then you will need to also change the app registry inside the settings.py file...etc..).
Instead add an attribute to the class like so to it:
verbose_name = "The Name You Like"
That should do the trick. Feel free to read up more about it on the official Django documentation page.

Why do I have to reference the user model this way

I was working on a Django project and I was trying to do something like this to make sure that my model worked no matter what user model is set.
from django.contrib.auth import get_user_model
class Item(models.Model):
title = models.CharField(max_length=100, )
description = models.TextField()
seller = models.ForeignKey(get_user_model())
However when I did this it resulted in errors telling me the user model couldn't be accessed so I had to change it to this
from django.conf import settings
class Item(models.Model):
title = models.CharField(max_length=100, )
description = models.TextField()
seller = models.ForeignKey(settings.AUTH_USER_MODEL)
This works fine but I thought I have done this in the past using the first method. The only difference that time being that I was using a custom user model. They both seem like they are doing the same thing to me so why do I have to use the second method? And does get_user_model() not work with the default user?
This is the source code of the get_user_model() in django:
def get_user_model():
"""
Returns the User model that is active in this project.
"""
from django.db.models import get_model
try:
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
except ValueError:
raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
user_model = get_model(app_label, model_name)
if user_model is None:
raise ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)
return user_model
As you can see, it pulls the AUTH_USER_MODEL variable from your settings as you do but extracting the app_label and the user class itself. If it does not work you should see one of the two errors in the terminal when this call is done.
I think your answer lies in the Django source. It depends on your setup what happens. Older versions might do it a bit differently.

DetailView using two ForeignKey kwargs

I am trying to utilize Django's class-based generic DetailView by querying the table using two keyword arguments passed via the url. I have tried overriding both the get_queryset() and get_object() method to no avail. My models look like this (edited for brevity, but let me know if something important is missing):
# models
class Skill(models.Model):
skill = models.CharField()
class User(AbstractBaseUser):
username = models.CharField()
class UserSkills(models.Model):
skill = models.ForeignKey(Skill)
user = models.ForeignKey(User, to_field='username')
value = models.CharField()
my url for the DetailView looks like this:
url(
regex=r"^(?P<username>[a-zA-Z0-9-]{1,25})/skills/(?P<skill>[a-zA-Z0-9 -._/]+)/$",
view=views.UserSkillDetail.as_view(),
name='userskill_detail',
),
the view:
class UserSkillDetail(DetailView):
template_name = 'UserSkill_detail.html'
context_object_name = 'skill'
model = UserSkills
def get_object(self, queryset=None):
get_user = self.kwargs['username']
get_skill = self.kwargs['skill']
return get_object_or_404(UserSkills, user__username=get_user, skill__skill=get_skill)
I keep receiving the following error via the template debug message:
No UserSkills matches the given query.
although I am able to successfully query the following via the shell:
>>> x = UserSkills.objects.get(user__username='user1', skill__skill='skill1')
>>> x
<UserSkills: user1#example.com: skill1>
and have verified that the keyword arguments are being captured correctly ('user1', 'skill1') via the logger and Django debug toolbar. Any help would be greatly appreciated!
There was an issue with my migration sequence (called out of intended order). I reconfigured the migrations and everything worked.

Django, Howto connect (and extent) facebook and django-userena or similar

It's been explicitly written in Django-facebook that they recommend it to be used with Userena:
We recommend using Django Userena. It seems easier to work with than
Django Registration. Both are supported and good packages though. To
use django userena simply point to the userena compatability layer.
AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile'
My question comes from AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile' part.
I have developed my own UserProfile in Userena and also inherited some system Actors like Student and Tutors based upon their own needs. so my setting is something like this:
AUTH_PROFILE_MODULE = 'profiles.UserProfile'
Within the django-facebook there is also an awesome example project that has written for mixing userena and django-facebook settings. But my problem still exists..
Should I replace my own code with facebook's one ??
This is my code :
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.db.models import permalink
from userena.models import UserenaBaseProfile
from courses.models import Course
class UserProfile(UserenaBaseProfile):
user = models.OneToOneField(User, unique=True, verbose_name=_('user'), related_name='user_profile')
department = models.ForeignKey('Department' , null = True , blank = True , related_name=_('user'))
name = models.CharField(max_length = 100)
birthday = models.DateField()
def __unicode__(self):
return self.name
class Student(UserProfile):
courses = models.ManyToManyField(Course , null = True, blank = True, related_name = _('student'))
Thanks beforehand ..
Just add the fields required for Facebook to your existing profile.
class UserProfile(UserenaBaseProfile, FacebookProfileModel):
....
(https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance)