I have build a record keeping app. I want the user to be able to edit an event but without updating the Date/TimeField when those are set to auto_now=True.
models.py
class Game(models.Model):
# ForeignKeys
user = models.ForeignKey(User,
max_length=10,
on_delete=models.CASCADE,
null=True)
deck = models.ForeignKey(Deck, on_delete=models.CASCADE, null=True)
wincon = models.ForeignKey(Wincon, on_delete=models.CASCADE, null=True, blank=True)
tournament = models.BooleanField(default=False)
num_players = models.IntegerField(choices=NUM_PLAYERS_CHOICE, default=4)
start_pos = models.CharField(max_length=20, choices=START_POS_CHOICE, default=1)
mull = models.CharField(max_length=20, choices=MULL_CHOICE, default='1st 7')
outcome = models.CharField(max_length=10, choices=OUTCOME_CHOICE, default='Win')
medium = models.CharField(max_length=10, choices=MEDIUM_CHOICE, default='Paper')
date = models.DateField(auto_now=True)
time = models.TimeField(auto_now=True)
forms.py
class GameForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super(GameForm, self).__init__(*args, **kwargs)
# Set deck list shown to only decks from user
user_decks = Deck.objects.filter(user=user)
user_decks_list = []
for deck in user_decks:
if deck.is_cedh:
deck.deck += ': cEDH'
user_decks_list.append((deck.id, deck.deck))
self.fields['deck'].choices = user_decks_list
# Set wincon list shown to only wincon from user
user_wincon = Wincon.objects.filter(user=user)
user_wincon_list = []
for wincon in user_wincon:
user_wincon_list.append((wincon.id, wincon.wincon))
self.fields['wincon'].choices = user_wincon_list
class Meta:
model = Game
exclude = {'date', 'time', 'user'}
labels = {
'deck': 'What deck',
'num_players': '# of Players',
'start_pos': 'Starting position',
'mull': 'Starting hand',
'outcome': 'Outcome',
'wincon': 'Your Wincon',
'medium': 'Paper or Online',
'tournament': 'Tournament',
}
class UpdateGameForm(forms.ModelForm):
class Meta:
model = Game
exclude = {'date', 'time', 'user'}
fields = {
'deck': 'What deck',
'num_players': '# of Players',
'mull': 'Starting hand',
'outcome': 'Outcome',
'wincon': 'Wincon',
'medium': 'Paper or Online',
'tournament': 'Tournament',
}
views.py
@login_required(login_url='my-login')
def game_tracker(request):
user = User.objects.get(username=request.user)
user_decks = Deck.objects.filter(user=request.user)
user_wincon = Wincon.objects.filter(user=request.user)
if request.method == "POST":
form = GameForm(request.user, request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.user = user
obj.save()
return HttpResponseRedirect('/view-games')
else:
form = GameForm(request.user)
context = {'form': form, 'user_decks': user_decks, 'user_wincon': user_wincon, 'user': user, }
return render(request, 'gametracker_app/gametracker.html', context=context)
@login_required(login_url='my-login')
def update_game(request, game_id):
game = Game.objects.get(pk=game_id)
form = UpdateGameForm(request.POST or None, instance=game)
if form.is_valid():
form.save()
return redirect('/view-games')
context = {'game': game, 'form': form}
return render(request, 'gametracker_app/update-game.html', context=context)
In forms.py I was trying to 'set' the date and time fields to what they previously were. This is what I had done with setting the 'deck' choices to the 'user_deck_list' but I don't know how to get the value of date/time to set the value because I am using auto_now=True in my models.
class UpdateGameForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UpdateGameForm, self).__init__(*args, **kwargs)
self.fields['date'] = 'date'
self.fields['time'] = 'time'
Use auto_now_add = True
because:
auto_now
option is used to set the value of the field to the current date and time every time the model instance is saved, regardless of whether it is being created or updated.
auto_now_add
option, on the other hand, is used to set the value of the field to the current date and time only when the model instance is created.