be used to display status messages to users based on their actions • Messages are set in the request, and are presented in a special message section of every page • Messages can have different “levels” of importance: • debug, info, success, warning, error • debug level doesn’t appear to users by default • Set MESSAGE_STORAGE in settings.py to use user session to hold messages • Ensure MIDDLEWARE_CLASSES contains MessageMiddleware: 3 'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.storage.session.SessionStorage'
INSTALLED_APPS has message application: • In view method, use messages.<LEVEL> to add a message that will be displayed the next time a template is rendered: • Messages are cleared whenever the message storage is iterated • In a template, this means whenever messages are included in the rendering of a page • Render messages in template by using messages template variable 4 'django.contrib.messages', 'django.contrib.messages.context_processors.messages' messages.debug(request, '5 SQL statements were executed.') messages.info(request, 'Three credits remain in your account.') messages.success(request, 'Profile details updated.') messages.warning(request, 'Your account expires in three days.') messages.error(request, 'Document deleted.')
from the database • Implemented as standard views, but with no actual rendering • If deletion is successful, user is redirected to another view • Necessary, since object being deleted no longer exists! • Add delete view to urls 7 def team_delete(request, team_id): try: team = models.Team.objects.get(pk=team_id) except models.Player.DoesNotExist: raise Http404 team.delete() messages.success(request, 'Team {0} deleted!'.format(team.name)) return redirect('team_list') url(r'^team/(?P<team_id>\d+)/delete/$', 'softball.views.team_delete', name='team_delete'),
circumstances and not in others • Related objects will be removed • If related objects aren’t removed, be sure to delete them, otherwise orphaned objects will remain in the database • Can be controlled on ForeignKeys by using the on_delete argument when declaring the ForeignKey • Generally will behave like a database ON DELETE CASCADE query • Use CASCADE when you want an object to be deleted when the object specified by ForeignKey is deleted • Add on_delete=django.db.models.CASCADE to all of the ForeignKeys in models.py • Use PROTECT when you want to prevent deletion of ForeignKey object • More information can be found in Django docs: • https://docs.djangoproject.com/en/1.4/ref/models/fields/ #django.db.models.ForeignKey.on_delete 8
additional fields that aren’t part of the Model • Works because ModelForms inherit from Django Forms • To add additional fields, configure them as in a normal Form • Use ModelChoiceField for GameForm since away_team and home_team are populated with Teams • Override clean() method to enable cleaning of additional fields 9 class GameForm(ModelForm): away_team = ModelChoiceField(label=u'Away Team', required=True, queryset=models.Team.objects.all(), help_text=u'Changing the team will clear the roster') home_team = ModelChoiceField(label=u'Home Team', required=True, queryset=models.Team.objects.all(), help_text=u'Changing the team will clear the roster')
ModelChoiceField(label=u'Away Team', required=True, queryset=models.Team.objects.all(), help_text=u'Changing the team will clear the roster') home_team = ModelChoiceField(label=u'Home Team', required=True, queryset=models.Team.objects.all(), help_text=u'Changing the team will clear the roster') error_css_class = 'text-error' required_css_class = 'text-required' class Meta: model = models.Game fields = ('played_on', 'location', ) def clean(self): cleaned_data = self.cleaned_data if cleaned_data.get('home_team') == cleaned_data.get('away_team') and\ cleaned_data['home_team']: msg = u'Home team and Away team cannot be the same.' self._errors['home_team'] = self.error_class([msg]) self._errors['away_team'] = self.error_class([msg]) # These fields are no longer valid. Remove them from the # cleaned data. del cleaned_data['home_team'] del cleaned_data['away_team'] return cleaned_data
FormFields in a view, treat the form as both Form and ModelForm • is_valid() still works, validating input for both instance and additional fields • save() will return the instance without the extra fields (they are just part of the form, not the Model) • form.cleaned_data can be used to access the extra fields • Be sure to include initialization of the extra fields by providing an initial data dict to set the pre-filled values for the extra fields in addition to providing an instance! • For GameForm and game_create view, this technique allows using the Game Model for location and played_on date fields, but using manually managed home_team and away_team fields for creating/editing rosters automatically • Additional fields will appear automatically AFTER configured ModelFields when rendering the Form