Reputation: 119
Hey sorry if that questions has been asked before but i havent found a fix yet looking at the previous questions.
i am trying to use django-booking (https://github.com/bitlabstudio/django-booking/tree/master/booking) on my website/app, now i can do the booking as a client and save it, but in the admin side if i click on bookings, i get and error
> TypeError at /admin/booking/booking/
>
> __str__ returned non-string (type NoneType)
>
> Request Method: GET Request URL:
> http://127.0.0.1:8000/admin/booking/booking/ Django Version: 2.0.8
> Exception Type: TypeError Exception Value:
>
> __str__ returned non-string (type NoneType)
>
> Exception Location: C:\Program
> Files\Python37\lib\site-packages\django\contrib\admin\templatetags\admin_list.py
> in items_for_result, line 235 Python Executable: C:\Program
> Files\Python37\python.exe Python Version: 3.7.0 Python Path:
>
> ['C:\\Users\\Agustin Landivar\\Desktop\\Marie\\drLandivar',
> 'C:\\Program Files\\Python37\\python37.zip', 'C:\\Program
> Files\\Python37\\DLLs', 'C:\\Program Files\\Python37\\lib',
> 'C:\\Program Files\\Python37', 'C:\\Program
> Files\\Python37\\lib\\site-packages']
>
> Server time: Tue, 21 Aug 2018 15:20:18 +0000 Error during template
> rendering
>
> In template C:\Program
> Files\Python37\lib\site-packages\django\contrib\admin\templates\admin\base.html,
> error at line 70
how can i fix that to be able to see all the bookings in the admin without getting this error, i see that normally this error is because of a str, but its also says that the error is in the django/contrib folder which i never touch :/
admin.py
"""Admin classes for the booking app."""
from django.contrib import admin
from hvad.admin import TranslatableAdmin
from . import models
from booking.models import Booking
class BookingAdmin(admin.ModelAdmin):
list_display = [
'creation_date', 'booking_status', 'booking_id', 'user', 'email',
'session', 'date_from', 'date_until',
]
class BookingItemAdmin(admin.ModelAdmin):
list_display = ['booking', 'booked_item', 'quantity', 'persons']
admin.site.register(models.Booking, BookingAdmin)
admin.site.register(models.BookingError)
admin.site.register(models.BookingItem, BookingItemAdmin)
admin.site.register(models.BookingStatus, TranslatableAdmin)
admin.site.register(models.ExtraPersonInfo)
forms.py
"""Forms for the ``booking`` app."""
from django import forms
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext_lazy as _
from .models import Booking, BookingStatus
class BookingForm(forms.ModelForm):
def __init__(self, session=None, user=None, *args, **kwargs):
self.user = user
self.session = session
super(BookingForm, self).__init__(*args, **kwargs)
# fields that should remain blank / not required
keep_blank = [
'phone', 'notes', 'street2', 'title', 'user', 'session',
'date_from', 'date_until', 'special_request', 'time_period',
'time_unit', 'email', 'currency', 'total']
# set all fields except the keep_blank ones to be required, since they
# need to be blank=True on the model itself to allow creating Booking
# instances without data
for name, field in self.fields.items():
if name not in keep_blank:
self.fields[name].required = True
def save(self, *args, **kwargs):
if not self.instance.pk:
self.instance.user = self.user
self.instance.session = self.session
status_object, created = BookingStatus.objects.get_or_create(
slug=getattr(settings, 'BOOKING_STATUS_CREATED', 'pending'))
self.instance.booking_status = status_object
return super(BookingForm, self).save(*args, **kwargs)
class Meta:
model = Booking
fields = ('gender', 'title', 'forename', 'surname', 'nationality',
'street1', 'street2', 'city', 'zip_code', 'country', 'phone',
'special_request', 'date_from', 'date_until')
class BookingIDAuthenticationForm(AuthenticationForm):
def __init__(self, *args, **kwargs):
super(BookingIDAuthenticationForm, self).__init__(*args, **kwargs)
self.fields['username'] = forms.CharField(
label=_("Email"), max_length=256)
self.fields['password'] = forms.CharField(
label=_("Booking ID"), max_length=100)
def clean_username(self):
"""Prevent case-sensitive erros in email/username."""
return self.cleaned_data['username'].lower()
def clean(self):
email = self.cleaned_data.get('username')
booking_id = self.cleaned_data.get('password')
if email and booking_id:
self.user_cache = authenticate(username=email,
password=booking_id)
if self.user_cache is None:
raise forms.ValidationError(_(
'We cannot find a valid booking ID for this email'
' address.')
)
elif not self.user_cache.is_active:
raise forms.ValidationError(self.error_messages['inactive'])
self.check_for_test_cookie()
return self.cleaned_data
models.py
"""Models for the ``booking`` app."""
from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django_libs.models_mixins import TranslationModelMixin
from django_countries.fields import CountryField
from hvad.models import TranslatableModel, TranslatedFields
from drLandivar import settings
class BookingStatus(TranslationModelMixin, TranslatableModel):
"""
Master data containing all booking status.
For translatable fields check ``BookingStatusTranslation``.
:slug: A unique slug identifier.
translated:
:name: The displayable name for the status.
"""
slug = models.SlugField(
verbose_name=_('Slug'),
)
translations = TranslatedFields(
name=models.CharField(
verbose_name=_('Name'),
max_length=128,
)
)
@python_2_unicode_compatible
class Booking(models.Model):
user = models.ForeignKey(
'users.CustomUser',
verbose_name=_('User'),
related_name='bookings',
blank=True, null=True,
on_delete=models.CASCADE,
)
session = models.ForeignKey(
'sessions.Session',
verbose_name=_('Session'),
blank=True, null=True,
on_delete=models.CASCADE,
)
gender = models.CharField(
max_length=10,
verbose_name=_('Gender'),
choices=(
('mrs', _('Mrs')),
('mr', _('Mr')),
),
blank=True,
)
title = models.CharField(
max_length=10,
verbose_name=_('Title'),
choices=(
('dr', _('Dr.')),
('prof', _('Prof.')),
),
blank=True,
)
forename = models.CharField(
verbose_name=_('First name'),
max_length=20,
blank=True,
)
surname = models.CharField(
verbose_name=_('Last name'),
max_length=20,
blank=True,
)
nationality = CountryField(
max_length=2,
verbose_name=_('Nationality'),
blank=True,
)
street1 = models.CharField(
verbose_name=_('Street 1'),
max_length=256,
blank=True,
)
street2 = models.CharField(
verbose_name=_('Street 2'),
max_length=256,
blank=True,
)
city = models.CharField(
verbose_name=_('City'),
max_length=256,
blank=True,
)
zip_code = models.CharField(
verbose_name=_('ZIP/Postal code'),
max_length=256,
blank=True,
)
country = CountryField(
max_length=2,
verbose_name=_('Country'),
blank=True,
)
email = models.EmailField(
verbose_name=_('Email'),
blank=True,
)
phone = models.CharField(
verbose_name=_('Phone'),
max_length=256,
blank=True,
)
special_request = models.TextField(
max_length=1024,
verbose_name=_('Special request'),
blank=True,
)
date_from = models.DateTimeField(
verbose_name=_('From'),
blank=True, null=True,
)
date_until = models.DateTimeField(
verbose_name=_('Until'),
blank=True, null=True,
)
creation_date = models.DateTimeField(
verbose_name=_('Creation date'),
auto_now_add=True,
)
booking_id = models.CharField(
max_length=100,
verbose_name=_('Booking ID'),
blank=True,
)
booking_status = models.ForeignKey(
'booking.BookingStatus',
verbose_name=('Booking status'),
blank=True, null=True,
on_delete=models.CASCADE,
)
notes = models.TextField(
max_length=1024,
verbose_name=('Notes'),
blank=True,
)
time_period = models.PositiveIntegerField(
verbose_name=_('Time period'),
blank=True, null=True,
)
time_unit = models.CharField(
verbose_name=_('Time unit'),
default=getattr(settings, 'BOOKING_TIME_INTERVAL', ''),
max_length=64,
blank=True,
)
total = models.DecimalField(
max_digits=36,
decimal_places=2,
verbose_name=_('Total'),
blank=True, null=True,
)
currency = models.CharField(
verbose_name=_('Currency'),
max_length=128,
blank=True,
)
class Meta:
ordering = ['-creation_date']
def __str__(self):
return '#{} ({})'.format(self.booking_id or self.pk,
self.creation_date)
@python_2_unicode_compatible
class BookingError(models.Model):
booking = models.ForeignKey(
Booking,
verbose_name=_('Booking'),
on_delete=models.CASCADE,
)
message = models.CharField(
verbose_name=_('Message'),
max_length=1000,
blank=True,
)
details = models.TextField(
verbose_name=_('Details'),
max_length=4000,
blank=True,
)
date = models.DateTimeField(
verbose_name=_('Date'),
auto_now_add=True,
)
def __str__(self):
return u'[{0}] {1} - {2}'.format(self.date, self.booking.booking_id,
self.message)
@python_2_unicode_compatible
class BookingItem(models.Model):
quantity = models.PositiveIntegerField(
default=1,
verbose_name=_('Quantity'),
)
persons = models.PositiveIntegerField(
verbose_name=_('Persons'),
blank=True, null=True,
)
subtotal = models.DecimalField(
max_digits=36,
decimal_places=2,
verbose_name=_('Subtotal'),
blank=True, null=True,
)
# GFK 'booked_item'
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,)
object_id = models.PositiveIntegerField()
booked_item = GenericForeignKey('content_type', 'object_id')
booking = models.ForeignKey(
'booking.Booking',
verbose_name=_('Booking'),
on_delete=models.CASCADE,
)
class Meta:
ordering = ['-booking__creation_date']
def __str__(self):
return u'{} ({})'.format(self.booking, self.booked_item)
@property
def price(self):
return self.quantity * self.subtotal
@python_2_unicode_compatible
class ExtraPersonInfo(models.Model):
"""
Model to add extra information of persons/guests to a booking.
:forename: First name of the user.
:surname: Last name of the user.
:arrival: Arrival date of the guest.
:booking: Connection to related booking.
:message: An additional message regarding this person.
"""
forename = models.CharField(
verbose_name=_('First name'),
max_length=20,
)
surname = models.CharField(
verbose_name=_('Last name'),
max_length=20,
)
arrival = models.DateTimeField(
verbose_name=_('Arrival'),
blank=True, null=True,
)
booking = models.ForeignKey(
'booking.Booking',
verbose_name=_('Booking'),
on_delete=models.CASCADE,
)
message = models.TextField(
max_length=1024,
verbose_name=_('Message'),
blank=True,
)
class Meta:
ordering = ['-booking__creation_date']
def __str__(self):
return u'{} {} ({})'.format(self.forename, self.surname, self.booking)
views.py
from django.shortcuts import render
# Create your views here.
"""Views for the booking app."""
from django.contrib.auth.decorators import login_required
from django.contrib.sessions.models import Session
from django.urls import reverse
from django.http import Http404
from django.utils.decorators import method_decorator
from django.views.generic import CreateView, DetailView, ListView
from .forms import BookingForm
from .models import Booking
# ------ MIXINS ------ #
class BookingViewMixin(object):
model = Booking
form_class = BookingForm
# ------ MODEL VIEWS ------ #
class BookingCreateView(BookingViewMixin, CreateView):
"""View to create a new ``Booking`` instance."""
def get_success_url(self):
return reverse('booking_detail', kwargs={'pk': self.object.pk})
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(BookingCreateView, self).get_form_kwargs(
*args, **kwargs)
if self.request.user.is_authenticated:
kwargs.update({'user': self.request.user})
else:
# If the user is not authenticated, get the current session
if not self.request.session.exists(
self.request.session.session_key):
self.request.session.create()
kwargs.update({'session': Session.objects.get(
session_key=self.request.session.session_key)})
return kwargs
class BookingDetailView(BookingViewMixin, DetailView):
"""View to display a ``Booking`` instance."""
def dispatch(self, request, *args, **kwargs):
self.kwargs = kwargs
self.object = self.get_object()
if request.user.is_authenticated:
# If user doesn't own the booking forbid access
if not self.object.user == request.user:
raise Http404
else:
# If anonymous doesn't own the booking forbid access
session = self.object.session
if (not session or not request.session.session_key or
session.session_key != request.session.session_key):
raise Http404
return super(BookingViewMixin, self).dispatch(request, *args, **kwargs)
class BookingListView(BookingViewMixin, ListView):
"""View to display all ``Booking`` instances of one user."""
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(BookingViewMixin, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
return self.request.user.bookings.all()
Upvotes: 0
Views: 2671
Reputation: 392
From my experience, this error happens when at least one of the variables used in str function is None. Check the objects from all models in your database from the shell and look for variables mentioned in str functions. If any of them is None, fix it. Note that you may get this error while visiting pages not related to the faulty object. Good Luck
Upvotes: 3