我一直在努力,整整一周,我需要把它休息一劳永逸。这可能看起来像很多代码,但核心是一个简单的概念问题。使用OneToOne /外地
我有一个模型,用户配置,具有以下字段:
user = models.OneToOneField(User)
weekOne = models.OneToOneField(WeekOne)
weekTwo = models.OneToOneField(WeekTwo)
WeekOne和WeekTwo与从被称为周的自定义类继承了自己独特的领域(models.Model)两种型号。周刚有一些自定义的功能,以节省为每个星期方法的一些重新打字和下面的代码,使之成为抽象类:
class Meta:
abstract = True
基本上,我希望每个用户都有一个唯一的weekOne和weekTwo(以及更多)字段,该字段具有对用户唯一的值的自定义字段。
当我第一次创建一个用户(即,用户注册时),我用views.py
下面的代码:
def signup(request):
user_form = UserCreateForm(data=request.POST)
if request.method == 'POST':
if user_form.is_valid():
username = user_form.clean_username()
password = user_form.clean_password2()
user_form.save()
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/')
else:
return index(request, user_form=user_form)
return redirect('/')
基本形式注册的东西,一切都一直工作在这里很好。
现在,这里是事情变得危险的地方。我有weekOne一种观点认为,可以确保用户的个人资料已经建立,并创建一个如果没有,代码是如下:
@login_required
def workout1(request):
template = "workout1.html"
weekOne = WeekOne()
weekOne.save()
user, created = UserProfile.objects.get_or_create(user=request.user,
defaults = {'weekOne': weekOne})
name = weekOne.__unicode__()
if created:
context = {'user': user}
return render(request, template, context)
# Grab already existing User Profile
weekOne.delete() # Was never used
context = {'user': user, 'name': name}
return render(request, template, context)
好。所以这很酷。但是当我尝试去第一周的页面时,出现以下错误:
workout_game_app_userprofile.weekTwo_id may not be NULL
这是我迷路的地方。我应该为每个单周视图初始化每个星期的变量吗?即,对于第一周的观点,我应该是这样做的代码:
weekOne = WeekOne()
weekTwo = WeekTwo()
weekThree = WeekThree()
等等?如果我必须在我计划实施的所有12周内完成这项工作,这似乎是荒谬的重复。
顺便说一句,我的模型在我实施第二周之前运转良好。
此外,OneToOne是否使用正确的钥匙?我想做一些事情,比如访问user.weekOne.item1,user.weekOne.item2等等,并且只为那个用户更改和保存它们的值。
UPDATE
:对于Sidharth沙阿,这里是从我的观点和模型的其余代码:
views.py:
from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.models import User
from workout_game_app.forms import AuthenticateForm, UserCreateForm
from workout_game_app.models import WeekOne, WeekTwo, UserProfile
from django.http import Http404, HttpResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.core import serializers
import simplejson
def index(request, auth_form=None, user_form=None):
if request.user.is_authenticated():
user = request.user
name = "Missions Overview"
context = {'user': user, 'name': name}
template = 'workouts.html'
return render(request, template, context)
else:
auth_form = auth_form or AuthenticateForm()
user_form = user_form or UserCreateForm()
template = 'index.html'
context = {'auth_form': auth_form, 'user_form': user_form}
return render(request, template, context)
def login_view(request):
if request.method == 'POST':
form = AuthenticateForm(data=request.POST)
if form.is_valid():
login(request, form.get_user())
return redirect('/')
else:
return index(request, auth_form=form)
return redirect('/')
def signup(request):
user_form = UserCreateForm(data=request.POST)
if request.method == 'POST':
if user_form.is_valid():
username = user_form.clean_username()
password = user_form.clean_password2()
user_form.save()
user = authenticate(username=username, password=password)
login(request, user)
return redirect('/')
else:
return index(request, user_form=user_form)
return redirect('/')
@login_required
def submitWorkout1(request):
if request.method == 'POST':
exercise = request.POST['exercise']
try:
amount = request.POST['amount']
except KeyError: # No amount field on form
amount = ""
user = UserProfile.objects.get(user=request.user)
week = user.weekOne
exercise, amount, exerciseComplete, allComplete = user.updateExercise(week, exercise, amount)
data = simplejson.dumps({
'result': 'success',
'exercise': exercise,
'amount': amount,
'exerciseComplete': exerciseComplete,
'allComplete': allComplete
}, indent=4)
return HttpResponse(data)
@login_required
def workout2(request):
template = "workout2.html"
weekTwo = WeekTwo()
weekTwo.save()
user, created = UserProfile.objects.get_or_create(user=request.user,
defaults = {'weekTwo': weekTwo})
name = weekTwo.__unicode__()
if created:
context = {'user': user}
return render(request, template, context)
# Grab already existing User Profile
weekTwo.delete() # Was never used
context = {'user': user, 'name': name}
return render(request, template, context)
@login_required
def submitWorkout2(request):
if request.method == 'POST':
exercise = request.POST['exercise']
try:
amount = request.POST['amount']
except KeyError: # No amount field on form
amount = ""
user = UserProfile.objects.get(user=request.user)
week = user.weekTwo
exercise, amount, exerciseComplete, allComplete = user.updateExercise(week, exercise, amount)
data = simplejson.dumps({
'result': 'success',
'exercise': exercise,
'amount': amount,
'exerciseComplete': exerciseComplete,
'allComplete': allComplete
}, indent=4)
return HttpResponse(data)
和models.py:
from django.db import models
from django.contrib.auth.models import User
class Week(models.Model):
# List of exercises by name for the week
exercises = []
# Week name in unicode
name = u''
# Running count of benchmarks met.
completeCount = models.PositiveSmallIntegerField(default=0)
# Set to true if benchmarks reached.
weekComplete = models.BooleanField(default=False)
# A bunch of methods
class WeekOne(Week):
name = u'Mission One'
exercises = ['squats', 'lunges', 'stairDaysCount', 'skipStairs']
# Required benchmarks for given exercises
squatBenchmark = 1000
lungeBenchmark = 250
stairDaysCountBenchmark = 3
totalGoals = 4
squats = models.PositiveIntegerField(default=0)
lunges = models.PositiveIntegerField(default=0)
skipStairs = models.BooleanField(default=False)
stairDaysCount = models.PositiveSmallIntegerField(default=0)
# A bunch of methods
class WeekTwo(Week):
name = u'Mission Two'
exercises = ['up3Levels', 'noHands', 'treadmill', 'vagMachine', 'extendedStairs']
totalGoals = 5
up3Levels = models.BooleanField(default=False)
noHands = models.BooleanField(default=False)
treadmill = models.BooleanField(default=False)
vagMachine = models.BooleanField(default=False)
extendedStairs = models.BooleanField(default=False)
# A bunch of methods
class UserProfile(models.Model):
user = models.OneToOneField(User)
weekOne = models.OneToOneField(WeekOne, null=True, default=None)
weekTwo = models.OneToOneField(WeekTwo, null=True, default=None)
# Some methods
和,虽然它工作正常,我的forms.py好措施:
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from django.contrib.auth.models import User
from django import forms
from django.utils.html import strip_tags
class UserCreateForm(UserCreationForm):
username = forms.CharField(required=True,
widget = forms.widgets.TextInput(attrs={'placeholder': 'Username'}))
password1 = forms.CharField(required=True,
widget = forms.widgets.PasswordInput(attrs={'placeholder': 'Password'}))
password2 = forms.CharField(required=True,
widget = forms.widgets.PasswordInput(attrs={'placeholder': 'Password'}))
def is_valid(self):
form = super(UserCreateForm, self).is_valid()
for f, error in self.errors.iteritems():
if f != '__all_':
self.fields[f].widget.attrs.update({'class':'error', 'value':strip_tags(error)})
return form
class Meta:
fields = ['username', 'password1', 'password2']
model = User
class AuthenticateForm(AuthenticationForm):
username = forms.CharField(
widget = forms.widgets.TextInput(attrs={'placeholder':'Username'}))
password2 = forms.CharField(
widget = forms.widgets.PasswordInput(attrs={'placeholder': 'Password'}))
奇怪的是,当我试图做到这一点后,我试图更新我的数据库后出现此错误:'DatabaseError:table“workout_game_app_weekone”已存在'。我只是处理测试数据,因此我首先使用'flush'命令删除了整个数据库,然后直接删除数据库文件 - 仍然出现错误。至于WeekOne和WeekTwo中的字段,它们都具有默认值。 – user1427661 2013-03-27 03:38:25
这是您为什么应该使用类似[南](http://south.aeracode.org/)的完美用例。它会照顾你的数据库迁移。如果你不介意你能分享你的代码,我可以克隆并看看发生了什么? – 2013-03-27 04:05:37
这是最糟糕的部分 - 我使用南方。我已经使用底部的全部视图,模型和表单更新了我的帖子。 – user1427661 2013-03-27 12:28:42