如何链接这两个模型,以便更新同一个实例?

时间:2021-08-21 07:23:44

I really want to build this app with Django that lets people register and create User instances that can be edited. Each User instance is already linked to a UserProfile with OneToOne because I didn't want to mess with the original User model. The UserProfile will have a field where he/she can register a game if that person is logged in.

我真的想用Django构建这个应用程序,让人们注册并创建可以编辑的用户实例。每个用户实例已经与OneToOne链接到UserProfile,因为我不想弄乱原始用户模型。如果该用户已登录,则UserProfile将具有他/她可以注册游戏的字段。

ie. Billy wants to register for Monday Smash Melee. He logs in, clicks an option on a form, the UserProfile linked to User, Billy, will update the registered game choice and user tag to the user profile.

即。比利想要在周一Smash Melee注册。他登录,点击表单上的选项,链接到User,Billy的UserProfile会将注册的游戏选择和用户标签更新为用户配置文件。

The part with the user profile linking to the user works fine, but I don't know how to update the UserProfile with the new tournament registration form so that it can change the UserProfile fields that's linked to the user that is logged in.

具有链接到用户的用户配置文件的部分工作正常,但我不知道如何使用新的锦标赛注册表单更新UserProfile,以便它可以更改链接到登录用户的UserProfile字段。

Django Models:

Django模型:

class UserProfile(models.Model):
#User profile for registered users. SEPARATE USERBASE TO PLAYER_RANKING
#To Do: add more customizeability and more access for registered.
#weekly e-mails, ability to register for weeklies...
user = models.OneToOneField(User)
picture = models.ImageField(upload_to='profile_images', blank=True)


MON = 'ME'
TUE = 'S4'
THR = 'PM'
reg_game_choices = (
    (MON, "Melee"),
    (TUE, "Smash 4"),
    (THR, "PM"),
    )
reg_game_choice = models.CharField(max_length=2,
                                   choices=reg_game_choices,
                                   default="")
user_tag = models.CharField(max_length=60, default = "")

def __str__(self):
    return self.user.username

Forms:

形式:

class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())

class Meta:
    model = User
    fields = ('username', 'password')

class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ('picture',)

class TournyRegForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ('reg_game_choice', 'user_tag',)

View:

视图:

@login_required
def tourny_reg(request):
    #Registering for tournaments
    context_dict = {}

    weekday = datetime.datetime.today().weekday()
    day_names = ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']
    game_days = ['SMASH MELEE', 'SMASH 4', 'CLOSED', 'PROJECT M &     FIGHTING GAMES',
            'FRIENDLIES', 'CLOSED', 'CLOSED']
    day_title = day_names[weekday]
    game_day = game_days[weekday]


    context_dict['day'] = day_title
    context_dict['game_of_the_day'] = game_day

    if request.method == 'POST':
        tourny_form = TournyRegForm(data=request.POST)
        if tourny_form.is_valid():
            tourny_form.save()
        else:
            print (tourny_form.errors)
    else:
        tourny_form = TournyRegForm()

    context_dict['tourny_form'] = tourny_form



return render(request, 'Kappa/tourny_reg.html', context_dict)

It shows up perfectly fine in html and on the local server, but when I try, it gives me an integrity error.

它在html和本地服务器上显示完全正常,但是当我尝试时,它给了我一个完整性错误。

IntegrityError at /Kappa/tourny_reg/

/ Kappa / tourny_reg /的IntegrityError

NOT NULL constraint failed: Kappa_userprofile.user_id Exception Value:

NOT NULL约束失败:Kappa_userprofile.user_id异常值:

NOT NULL constraint failed: Kappa_userprofile.user_id ▶ Local vars C:\Users\Kyle\Documents\GitHub\Kappa_Ranks\Kappa\views.py in tourny_reg

NOT NULL约束失败:Kappa_userprofile.user_id▶tourny_reg中的本地变量C:\ Users \ Kyle \ Documents \ GitHub \ Kappa_Ranks \ Kappa \ views.py

1 个解决方案

#1


1  

So basically, you want to know how to save an instance of something which is related to the logged-in user. That's easy.

所以基本上,您想知道如何保存与登录用户相关的事物的实例。这很容易。

To explain why you are getting a NOT NULL error: Your TournyRegForm class has not been told to display an input field for 'user', so it isn't. So when you go to save the form, None is being filled in for the user field. The database is complaining because a 'NOT NULL' field has a NULL value, which is a problem.. so this error is legitimate.

解释为什么你得到一个NOT NULL错误:你的TournyRegForm类没有被告知显示'user'的输入字段,所以它不是。因此,当您去保存表单时,将为用户字段填写无。数据库抱怨,因为'NOT NULL'字段有一个NULL值,这是一个问题..所以这个错误是合法的。

But it's ok that this field is not on the form.. because you don't want the user telling us who they are via the form, you want to get the information about who they are by the fact that they are logged in. The Django auth module puts this information in the Request object where you can easily get at it. All you need to do is to fill in the correct user before the model is saved, like this:

但是这个字段不在表单上是好的..因为你不希望用户通过表单告诉我们他们是谁,你想通过他们登录的事实获得他们是谁的信息。 Django auth模块将此信息放在Request对象中,您可以轻松获取它。您需要做的就是在保存模型之前填写正确的用户,如下所示:

if tourny_form.is_valid():
    # commit= False tells the modelform to just create the model instance
    # but don't save it yet.
    user_profile = tourny_form.save(commit=False)
    # associate this user_profile with the logged in user.. it is always
    # present in the request object if you are using django's         auth module.
    user_profile.user = request.user
    # now save it
    user_profile.save()

So that takes care of saving a model that is related to the currently logged in user. But you have other problems. For example, do you want to save a new UserProfile each time? I don't think you do.. So on your GET you need to do something like this:

因此,它负责保存与当前登录用户相关的模型。但是你有其他问题。例如,您是否希望每次都保存新的UserProfile?我不认为你这样做..所以在你的GET上你需要做这样的事情:

user_profile = UserProfile.objects.filter(user=request.user).first()
tourny_form = TournyRegForm(instance=user_profile)

This will fetch the UserProfile of the currently logged=in user from the database, then initialize the form with that instance, so when the user comes back they will be able to edit their profile.

这将从数据库中获取当前记录的= in用户的UserProfile,然后使用该实例初始化表单,因此当用户返回时,他们将能够编辑他们的配置文件。

Now, if you actually want the user to be able to register for multiple games.. you will need a Game model for storing the game information, with one-to-many relationship with your UserProfile. This works by having a ForeignKey field in the Game model which relates it to UserProfile.. so each user will have only one UserProfile but could have multiple Games.

现在,如果你真的希望用户能够注册多个游戏......你需要一个游戏模型来存储游戏信息,与你的UserProfile有一对多的关系。这通过在Game模型中使用ForeignKey字段来实现,该字段将其与UserProfile相关联。因此每个用户将只有一个UserProfile但可以有多个Games。

#1


1  

So basically, you want to know how to save an instance of something which is related to the logged-in user. That's easy.

所以基本上,您想知道如何保存与登录用户相关的事物的实例。这很容易。

To explain why you are getting a NOT NULL error: Your TournyRegForm class has not been told to display an input field for 'user', so it isn't. So when you go to save the form, None is being filled in for the user field. The database is complaining because a 'NOT NULL' field has a NULL value, which is a problem.. so this error is legitimate.

解释为什么你得到一个NOT NULL错误:你的TournyRegForm类没有被告知显示'user'的输入字段,所以它不是。因此,当您去保存表单时,将为用户字段填写无。数据库抱怨,因为'NOT NULL'字段有一个NULL值,这是一个问题..所以这个错误是合法的。

But it's ok that this field is not on the form.. because you don't want the user telling us who they are via the form, you want to get the information about who they are by the fact that they are logged in. The Django auth module puts this information in the Request object where you can easily get at it. All you need to do is to fill in the correct user before the model is saved, like this:

但是这个字段不在表单上是好的..因为你不希望用户通过表单告诉我们他们是谁,你想通过他们登录的事实获得他们是谁的信息。 Django auth模块将此信息放在Request对象中,您可以轻松获取它。您需要做的就是在保存模型之前填写正确的用户,如下所示:

if tourny_form.is_valid():
    # commit= False tells the modelform to just create the model instance
    # but don't save it yet.
    user_profile = tourny_form.save(commit=False)
    # associate this user_profile with the logged in user.. it is always
    # present in the request object if you are using django's         auth module.
    user_profile.user = request.user
    # now save it
    user_profile.save()

So that takes care of saving a model that is related to the currently logged in user. But you have other problems. For example, do you want to save a new UserProfile each time? I don't think you do.. So on your GET you need to do something like this:

因此,它负责保存与当前登录用户相关的模型。但是你有其他问题。例如,您是否希望每次都保存新的UserProfile?我不认为你这样做..所以在你的GET上你需要做这样的事情:

user_profile = UserProfile.objects.filter(user=request.user).first()
tourny_form = TournyRegForm(instance=user_profile)

This will fetch the UserProfile of the currently logged=in user from the database, then initialize the form with that instance, so when the user comes back they will be able to edit their profile.

这将从数据库中获取当前记录的= in用户的UserProfile,然后使用该实例初始化表单,因此当用户返回时,他们将能够编辑他们的配置文件。

Now, if you actually want the user to be able to register for multiple games.. you will need a Game model for storing the game information, with one-to-many relationship with your UserProfile. This works by having a ForeignKey field in the Game model which relates it to UserProfile.. so each user will have only one UserProfile but could have multiple Games.

现在,如果你真的希望用户能够注册多个游戏......你需要一个游戏模型来存储游戏信息,与你的UserProfile有一对多的关系。这通过在Game模型中使用ForeignKey字段来实现,该字段将其与UserProfile相关联。因此每个用户将只有一个UserProfile但可以有多个Games。