2013-03-27 32 views
0

我一直在努力,整整一周,我需要把它休息一劳永逸。这可能看起来像很多代码,但核心是一个简单的概念问题。使用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'})) 

回答

1

你可能想有以下模型

user = models.OneToOneField(User) 
weekOne = models.OneToOneField(WeekOne, null=True, default=None) 
weekTwo = models.OneToOneField(WeekTwo, null=True, default=None) 

尝试了这一点,它应该工作。看着上面的代码,你正在定义的领域weekOne,weekTwo等。我不确定的是,如果你在创建它的时候分配所有必要的领域weekOne对象。

+0

奇怪的是,当我试图做到这一点后,我试图更新我的数据库后出现此错误:'DatabaseError:table“workout_game_app_weekone”已存在'。我只是处理测试数据,因此我首先使用'flush'命令删除了整个数据库,然后直接删除数据库文件 - 仍然出现错误。至于WeekOne和WeekTwo中的字段,它们都具有默认值。 – user1427661 2013-03-27 03:38:25

+0

这是您为什么应该使用类似[南](http://south.aeracode.org/)的完美用例。它会照顾你的数据库迁移。如果你不介意你能分享你的代码,我可以克隆并看看发生了什么? – 2013-03-27 04:05:37

+0

这是最糟糕的部分 - 我使用南方。我已经使用底部的全部视图,模型和表单更新了我的帖子。 – user1427661 2013-03-27 12:28:42