Crash validating related model created using inline admin - django

I'm creating a one-to-one model to extend the functionality of an existing model type, but I want it to only allow creating the extension model in certain cases. I enforce this constraint by throwing a ValidationError in the full_clean on the new Extended model. This works great when I create Extended models using Extended's ModelAdmin directly (it highlights the a field if it's the wrong type), but when I use StackedInline to inline Extended creation in As ModelAdmin, and A is the wrong type, the form fails to catch the ValidationError and I get the message A server error occurred. Please contact the administrator.
This is how I have the models set up:
# models.py
from django.db import models
class A(models.Model):
type = models.IntegerField(...)
class Extended(models.Model)
a = models.OneToOneField(A)
def clean_fields(self, **kwargs):
if self.a.type != 3:
raise ValidationError({'a': ["a must be of type 3"]})
super(Extended, self).clean_fields(**kwargs)
def save(self, *args, **kwargs):
self.full_clean()
super(Extended, self).save(*args, **kwargs)
# admin.py
from django.contrib import admin
class ExtendedInline(admin.StackedInline):
model = Extended
#admin.register(A)
class AAdmin(admin.ModelAdmin):
inlines = (ExtendedInline,)
The full traceback:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/wsgiref/handlers.py", line 85, in run
self.result = application(self.environ, self.start_response)
File "/usr/local/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 63, in __call__
return self.application(environ, start_response)
File "/usr/local/lib/python2.7/site-packages/whitenoise/base.py", line 66, in __call__
return self.application(environ, start_response)
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 189, in __call__
response = self.get_response(request)
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 218, in get_response
response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
File "/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 132, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 618, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py", line 110, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 233, in inner
return view(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1521, in change_view
return self.changeform_view(request, object_id, form_url, extra_context)
File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py", line 34, in _wrapper
return bound_func(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py", line 110, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py", line 30, in bound_func
return func.__get__(self, type(self))(*args2, **kwargs2)
File "/usr/local/lib/python2.7/site-packages/django/utils/decorators.py", line 145, in inner
return func(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1470, in changeform_view
self.save_related(request, form, formsets, not add)
File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1104, in save_related
self.save_formset(request, form, formset, change=change)
File "/usr/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1092, in save_formset
formset.save()
File "/usr/local/lib/python2.7/site-packages/django/forms/models.py", line 636, in save
return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/usr/local/lib/python2.7/site-packages/django/forms/models.py", line 767, in save_new_objects
self.new_objects.append(self.save_new(form, commit=commit))
File "/usr/local/lib/python2.7/site-packages/django/forms/models.py", line 900, in save_new
obj.save()
File "/code/app/models.py", line 162, in save
self.full_clean()
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 1171, in full_clean
raise ValidationError(errors)
ValidationError: {'a': [u'a must be of type 3']}
I'm currently using Django version 1.8

Inline foreignkeys are excluded on the calls to full_clean() that happen in modelform validators, so your ValidationError is not being caught by the form's is_valid() call.
From django/forms/models.py:
def _post_clean(self):
opts = self._meta
exclude = self._get_validation_exclusions()
try:
self.instance = construct_instance(self, self.instance, opts.fields, exclude)
except ValidationError as e:
self._update_errors(e)
# Foreign Keys being used to represent inline relationships
# are excluded from basic field value validation. This is for two
# reasons: firstly, the value may not be supplied (#12507; the
# case of providing new values to the admin); secondly the
# object being referred to may not yet fully exist (#12749).
# However, these fields *must* be included in uniqueness checks,
# so this can't be part of _get_validation_exclusions().
for name, field in self.fields.items():
if isinstance(field, InlineForeignKeyField):
exclude.append(name)
try:
self.instance.full_clean(exclude=exclude, validate_unique=False)
except ValidationError as e:
self._update_errors(e)
# Validate uniqueness if needed.
if self._validate_unique:
self.validate_unique()
They're being caught in save() instead (where you call full_clean without the exclusion), which is too late.
Move your validation to clean() instead:
def clean(self):
if self.a.type != 3:
raise ValidationError({'a': ["a must be of type 3"]})
Then there will be no need to call full_clean from your save method. This method is where any validation of this sort should go as per the docs.

If I change
raise ValidationError({'a': ["a must be of type 3"]})
to
raise ValidationError(["a must be of type 3"])
I don't get the crash and it appears on the inline admin.

I'm getting this in the a regular (non-inline) ModelAdmin, but this solution should also work.
I simply wrapped the save_model() in a try except and sent the exception message through a messages.warning()
from django.contrib import admin, messages
class ConstraintErrorBoundaryMixin:
def save_model(self, request, obj, form, change):
try:
super().save_model(request, obj, form, change)
except Exception as exc:
messages.error(request, str(exc))

Related

overriding empty_value_display for specified field not working in django Admin

I have written a model as follows:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3)
birth_date = models.DateField(blank=True, null=True)
And my modeladmin is as follows:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title', 'view_birth_date')
def view_birth_date(self, obj):
return obj.birth_date
view_birth_date.empty_value_display = '-empty-'
As documented in django 2.1 https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.empty_value_display, I am trying to do this but its not working.
Its gives me fielderror. Even I didn't understand its purpose.
My traceback:
Traceback (most recent call last):
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\options.py", line 703, in get_form
return modelform_factory(self.model, **defaults)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\forms\models.py", line 551, in modelform_factory
return type(form)(class_name, (form,), form_class_attrs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\forms\models.py", line 266, in __new__
raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (view_birth_date) specified for Author
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\options.py", line 604, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\utils\decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\views\decorators\cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\sites.py", line 223, in inner
return view(request, *args, **kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\options.py", line 1639, in change_view
return self.changeform_view(request, object_id, form_url, extra_context)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\utils\decorators.py", line 45, in _wrapper
return bound_method(*args, **kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\utils\decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\options.py", line 1525, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\options.py", line 1554, in _changeform_view
ModelForm = self.get_form(request, obj, change=not add)
File "C:\Users\monikat\Envs\django_training\lib\site-packages\django\contrib\admin\options.py", line 707, in get_form % (e, self.__class__.__name__)
django.core.exceptions.FieldError: Unknown field(s) (view_birth_date) specified for Author. Check fields/fieldsets/exclude attributes of class AuthorAdmin.
Does anyone know why this error is coming?
The problem is that you have defined view_birth_date in the fields attribute of model admin class.
Since it is not present in your db model, it is giving error. Such custom fields will work for list_display, in which you can fetch the value from a method as you have done above, see the docs.
Now if you want some custom field to display on the add/change page , you have to create a custom form and there you can define your custom fields.
If the custom field is just for representation , you can define it as readonly as :
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title', 'view_birth_date')
readonly_fields = ['view_birth_date']
def view_birth_date(self, obj):
return obj.title
view_birth_date.empty_value_display = '-empty-'
Hope it helps!

Can not save Django Proxy user model from Admin

I am getting the following error message when I save the user object. I have searched on the internet for the error message, but I can not find any help. It maybe somthing very obvious that I am missing, but I am not able to find any help available.
Can someone take a look and let me know what the error here is?
File admin.py
from django.contrib.auth.admin import UserAdmin
class UserAdmin(UserAdmin):
list_display = ('username', 'email', 'first_name', 'last_name',
'is_active', roles, login)
list_filter = ('groups',)
def save_model(self, request, obj, form, change):
queryset = MyUser.objects.filter(id=obj.id)
if obj.is_active:
logger.info('User is marked active')
elif not obj.is_active:
logger.info('User is marked inactive')
obj.save()
def add_view(self, *args, **kwargs):
self.inlines = []
return super(UserAdmin, self).add_view(*args, **kwargs)
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inlines = (ProfileInline,)
return super(UserAdmin, self).change_view(request, object_id, form_url, extra_context)
File models.py
class MyUser(User, URLGenerator):
objects = models.Manager() # The default manager.
safe = SafeUserManager()
class Meta:
proxy = True
ordering = ['username']
def __unicode__(self):
return self.get_full_name()
The ERROR I'm getting:
Internal Server Error: /admin/public/myuser/1/change/
Traceback (most recent call last):
File "/dp/app/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
response = self._get_response(request)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 551, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 224, in inner
return view(request, *args, **kwargs)
File "/dp/app/dpapp/public/admin.py", line 364, in change_view
return super(UserAdmin, self).change_view(request, object_id, form_url, extra_context)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1511, in change_view
return self.changeform_view(request, object_id, form_url, extra_context)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
return bound_func(*args, **kwargs)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
return func.__get__(self, type(self))(*args2, **kwargs2)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1408, in changeform_view
return self._changeform_view(request, object_id, form_url, extra_context)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1440, in _changeform_view
if form.is_valid():
File "/dp/app/venv/local/lib/python2.7/site-packages/django/forms/forms.py", line 183, in is_valid
return self.is_bound and not self.errors
File "/dp/app/venv/local/lib/python2.7/site-packages/django/forms/forms.py", line 175, in errors
self.full_clean()
File "/dp/app/venv/local/lib/python2.7/site-packages/django/forms/forms.py", line 386, in full_clean
self._post_clean()
File "/dp/app/venv/local/lib/python2.7/site-packages/django/forms/models.py", line 413, in _post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File "/dp/app/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 1235, in full_clean
self.clean()
File "/dp/app/venv/local/lib/python2.7/site-packages/django/contrib/auth/models.py", line 349, in clean
self.email = self.__class__.objects.normalize_email(self.email)
AttributeError: 'Manager' object has no attribute 'normalize_email'
Your User object doesn't have the manager method normalize_email. Try changing your user's manager to
objects = BaseUserManager()
which you can import in django.contrib.auth.base_user

Django FieldError only with debug disabled

I've got a Django project that throws me "FieldError: Cannot resolve keyword 'game' into field. Choices are: [list of choices]".
The funny thing is, it only occurs when DEBUG is disabled in settings.py. When DEBUG is enabled everything seems to work fine.
I have identified the code that triggers the error. My model looks like this:
from django.db import models
from django.forms import ModelForm
from time import strftime
from rostermaker.models import Player
from django.core.exceptions import ValidationError
from django.utils import timezone
class Game(models.Model):
when = models.DateTimeField(unique = True)
opponent = models.CharField(max_length = 50, default="TBD")
...
def __unicode__(self):
when = timezone.localtime(self.DateTime)
return when.strftime('%a, %b %d, %Y %I:%M %p')
class Stat(models.Model):
g = models.ForeignKey(Game, related_name = 'stat_game')
player = models.ForeignKey(Player, related_name = 'stat_player', limit_choices_to={'active': True})
...
In admin.py, the .count and .filter lines trigger the error:
def save_model(self, request, obj, form, change):
obj.save()
form.save_m2m()
count = obj.players.count()
women = obj.players.filter(sex='F')
women_count = women.count()
if count != 0:
women_pct = int((women_count/float(count))*100)
self.message_user(request,"Players scheduled: %s | Women: %s percent" % (count, women_pct))
else:
self.message_user(request,"Players scheduled: 0 | Women: 0 percent")
In a couple of views, lines similar to this one cause the error:
played_games_list = Game.objects.filter(DateTime__lte=timezone.now()).order_by('-when')
I'm using Django version 1.4 and PostgreSQL 8.4.20.
My best guess from what I've read here is that the Game class isn't loading properly. But why it appears to load properly when DEBUG is on mystifies me.
Any help is appreciated.
UPDATE: Traceback, as requested:
Traceback (most recent call last):
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/contrib/admin/options.py", line 366, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/utils/decorators.py", line 91, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/views/decorators/cache.py", line 89, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/contrib/admin/sites.py", line 196, in inner
return view(request, *args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/utils/decorators.py", line 25, in _wrapper
return bound_func(*args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/utils/decorators.py", line 91, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/utils/decorators.py", line 21, in bound_func
return func(self, *args2, **kwargs2)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/transaction.py", line 224, in inner
return func(*args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/contrib/admin/options.py", line 955, in add_view
self.save_model(request, new_object, form, False)
File "/home/bwareham/webapps/mprsb/myproject/rostermaker/admin.py", line 69, in save_model
count = obj.players.count()
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/manager.py", line 119, in count
return self.get_query_set().count()
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/fields/related.py", line 567, in get_query_set
return super(ManyRelatedManager, self).get_query_set().using(db)._next_is_sticky().filter(**self.core_filters)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/query.py", line 624, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/query.py", line 642, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/sql/query.py", line 1250, in add_q
can_reuse=used_aliases, force_having=force_having)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/sql/query.py", line 1122, in add_filter
process_extras=process_extras)
File "/home/bwareham/webapps/mprsb/lib/python2.7/django/db/models/sql/query.py", line 1316, in setup_joins
"Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'game' into field. Choices are: Hall of Fame, active, alias, battingchamps, bombat, captains, firstName, goldengloves, id, lastName, mostimproved, mvp, photo, rookies, roster, sex, walker, whippet
It was some sort of loading problem. Found solution here.
Am able to force model loading with this snippet before the admin autodiscover function in urls.py:
from django.db.models.loading import cache as model_cache
if not model_cache.loaded:
model_cache.get_models()
Thanks to all who tried to help me troubleshoot. I always learn something.

Cause of Django duplicate entry error (1062)?

I updated the info below to reference a different model/view that is giving me the same error. Its a simpler model so there are less variables to take into account...
I have the following model:
class Imaging_order(Order):
order_description = models.ForeignKey(Imaging_test, limit_choices_to = {'active': 1}, null=True, blank=True)
orders = models.ManyToManyField(Imaging_test, limit_choices_to = {'active': 1}, related_name='orders')
...
I have the following views (basically the generic django class based update view with a couple custom functions mixed in):
class LoginRequiredMixin(object):
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
class EditMixin(object):
def form_valid(self, form):
messages.success(self.request, "This %s has been updated." % (self.model._meta.verbose_name), extra_tags='msg')
return super(EditMixin, self).form_valid(form)
class ImagingMixin(LoginRequiredMixin):
model = Imaging_order
form_class = ImagingForm
class ImagingUpdateView(ImagingMixin, EditMixin, UpdateView):
pass
On our live version I occassionally get notices of this error:
Traceback (most recent call last):
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/views/generic/base.py", line 47, in view
return self.dispatch(request, *args, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/utils/decorators.py", line 28, in _wrapper
return bound_func(*args, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/utils/decorators.py", line 24, in bound_func
return func(self, *args2, **kwargs2)
File "/home/cpcadmin/webapps/cpcdj2/cpc/emr/views.py", line 150, in dispatch
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/views/generic/base.py", line 68, in dispatch
return handler(request, *args, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/views/generic/edit.py", line 195, in post
return super(BaseUpdateView, self).post(request, *args, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/views/generic/edit.py", line 138, in post
return self.form_valid(form)
File "/home/cpcadmin/webapps/cpcdj2/cpc/emr/views.py", line 155, in form_valid
return super(EditMixin, self).form_valid(form)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/views/generic/edit.py", line 112, in form_valid
self.object = form.save()
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/forms/models.py", line 363, in save
fail_message, commit, construct=False)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/forms/models.py", line 86, in save_instance
save_m2m()
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/forms/models.py", line 82, in save_m2m
f.save_form_data(instance, cleaned_data[f.name])
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/fields/related.py", line 1149, in save_form_data
setattr(instance, self.attname, data)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/fields/related.py", line 746, in __set__
manager.add(*value)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/fields/related.py", line 503, in add
self._add_items(self.source_field_name, self.target_field_name, *objs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/fields/related.py", line 587, in _add_items
'%s_id' % target_field_name: obj_id,
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/query.py", line 360, in create
obj.save(force_insert=True, using=self.db)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/base.py", line 460, in save
self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/base.py", line 553, in save_base
result = manager._insert(values, return_id=update_pk, using=using)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/manager.py", line 195, in _insert
return insert_query(self.model, values, **kwargs)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/query.py", line 1436, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/sql/compiler.py", line 791, in execute_sql
cursor = super(SQLInsertCompiler, self).execute_sql(None)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/models/sql/compiler.py", line 735, in execute_sql
cursor.execute(sql, params)
File "/home/cpcadmin/webapps/cpcdj2/lib/python2.7/django/db/backends/mysql/base.py", line 86, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 174, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
IntegrityError: (1062, "Duplicate entry '25129-18' for key 2")
I cannot tell when this error is occurring (usually this view works just fine). I think I have a normal model/view/form setup except that I extended the generic class-based views a bit. I agree with the below comment that this is related to a m2m field. Every time this error comes up it is calling "save_m2m", which then results in this error. I still can't reproduce it. It occurs from my update page/view so I think its only when updating an existing model with existing related records. This is the closest other post I could find, but was of no help: IntegrityError: (1062, "Duplicate entry '1830327-1792993' for key 'some_instance_A_id'") but no UNIQUE constraint

Django Admin Issue - 'NoneType' object has no attribute 'user'

Writing a blog engine with Django 1.5 and using the Django Admin. Everything was fine, until I added a ManyToManyField to a model, and added that field to the ModelAdmin's fieldsets, then I started to get this mysterious error when trying to load the admin page:
'NoneType' object has no attribute 'user'
(Full stack trace further on below.) Why would the response object suddenly be None? If I remove the field from the fieldset, everything's fine again.
My models look something a bit like this (lots of fields removed):
class Tag(models.Model):
name = models.CharField(max_length=30)
class Post(models.Model):
title = models.CharField(max_length=300)
tags = models.ManyToManyField(Tag)
author = models.CharField(max_length=100)
And the ModelAdmin looks a bit like this:
class PostAdmin(admin.ModelAdmin):
# Order
fieldsets = (
('Content', {
'fields': ('title', 'tags')
}),
)
def formfield_for_dbfield(self, db_field, request, **kwargs):
# Pre-fill 'author' with logged in name
if db_field.name == "author":
kwargs['initial'] = "%s %s" % (request.user.first_name, request.user.last_name)
return db_field.formfield(**kwargs)
return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
And it's when I remove 'tag's from the fieldsets that all is well again. It could be that I'm making some simple Django Admin mistake, I haven't used it much before, but the best I could find googling was some bug that was fixed three years ago, and I'm sure I'm running 1.5.1.
Here's the full stack trace:
Internal Server Error: /theadmin/blog/post/1/
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\django\core\handlers\base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 372, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 91, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\django\views\decorators\cache.py", line 89, in _wrapped_view_
unc
response = view_func(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\django\contrib\admin\sites.py", line 202, in inner
return view(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 25, in _wrapper
return bound_func(*args, **kwargs)
File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 91, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\django\utils\decorators.py", line 21, in bound_func
return func(self, *args2, **kwargs2)
File "C:\Python27\lib\site-packages\django\db\transaction.py", line 223, in inner
return func(*args, **kwargs)
File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 1081, in change_view
ModelForm = self.get_form(request, obj)
File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 465, in get_form
return modelform_factory(self.model, **defaults)
File "C:\Python27\lib\site-packages\django\forms\models.py", line 424, in modelform_factory
return type(form)(class_name, (form,), form_class_attrs)
File "C:\Python27\lib\site-packages\django\forms\models.py", line 212, in __new__
opts.exclude, opts.widgets, formfield_callback)
File "C:\Python27\lib\site-packages\django\forms\models.py", line 170, in fields_for_model
formfield = formfield_callback(f, **kwargs)
File "E:\Dropbox\PassionateAbout\PassionateAboutJustice\blog\admin.py", line 35, in formfield_for
dbfield
return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 125, in formfield_for_
bfield
related_modeladmin.has_add_permission(request))
File "C:\Python27\lib\site-packages\django\contrib\admin\options.py", line 284, in has_add_permis
ion
return request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
AttributeError: 'NoneType' object has no attribute 'user'
Your swallowing the request. Here you take it:
def formfield_for_dbfield(self, db_field, request, **kwargs):
but then you don't pass it on:
return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
However the original - https://github.com/django/django/blob/stable/1.5.x/django/contrib/admin/options.py#L88
is defined as:
def formfield_for_dbfield(self, db_field, **kwargs):
So you should keep the same signature when you override.
Please note: the original will do:
request = kwargs.pop("request", None)
If you want to access the request, don't do the same, because "pop()" will remove it from kwargs. Just access without deleting:
request = kwargs['request']
so your super call still passes the request through.
It only came to light with the M2M field because that needs the request to look up permissions of the current user (for the related model) whereas CharField doesn't really need the request, so doesn't mind that it's None. (which the above pop() call will do if request is not found)
End result:
def formfield_for_dbfield(self, db_field, **kwargs):
# Pre-fill 'author' with logged in name
if db_field.name == "author":
request = kwargs['request']
kwargs['initial'] = "%s %s" % (request.user.first_name, request.user.last_name)
return db_field.formfield(**kwargs)
return super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)