在保存为两个模型的表单之前设置ForeignKey

时间:2016-02-11 00:19:06

标签: python django

我一直在寻找这个,但找不到适合我情况的任何东西。我的应用中有UserUserProfile个模型。

我的forms.py看起来像这样:

from django import forms
from django.forms import ModelForm
from django.contrib.auth.models import User
from .models import UserProfile

class UserForm(ModelForm):

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

class  UserProfileForm(ModelForm):

    class Meta:
        model = UserProfile
        fields = ('display_name', 'avatar', 'birthday', 'usertype', 'daw', 'usergenre')

和我的views.py看起来像这样:

def RegisterView(request):
    if request.method == 'POST':
        form = UserForm(request.POST, prefix='uf')
        form2 = UserProfileForm(request.POST, prefix='upf')
        if form.is_valid():
            if form2.is_valid():
                form.save()
                form2.user = form.username
                form2.save()
                return HttpResponseRedirect('/')
    elif request.method == 'GET':
        form = UserForm(prefix='uf')
        form2 = UserProfileForm(prefix='upf')            

    return render(request, 'profile/register.html', {'form': form, 'form2': form2})

现在看我的问题是,当我保存UserProfile实例时,它没有与新保存的ForeignKey(User)实例相关的必需User设置,如何在保存之前设置它?显然我必须在保存User实例后执行此操作,但是如何获取我们刚刚创建的User实例的“request.user”并将UserProfile中的ForeignKey设置为?

models.py

from django.db import models
from django.core.exceptions import ValidationError
from django.core.files.images import get_image_dimensions
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from Submission.storage import OverwriteStorage

# Create your models here.
class UserProfile(models.Model):

    def is_square_png(self):
        if not self.name.endswith('.png'):
            raise ValidationError("You may only upload .png files!")
        else:
            w, h = get_image_dimensions(self)
            if not h == w:
                raise ValidationError("This picture is not square! Your picture must be equally wide as its height.")
            else:
                if not (h + w) >= 1000:
                    raise ValidationError("This picture is too small! The minimum dimensions are 500 by 500 pixels.")
                else:
                    if not (h + w) < 2000:
                        raise ValidationError("This picture is too big! The maximum dimensions are 1000 by 1000 pixels.")
        return self

    def generate_user_folder_avatar(instance, filename):
        return "static/users/%s/%s.png" % (instance.user, 'avatar')

    user = models.OneToOneField(User)
    display_name = models.CharField(max_length=50, default="null")
    avatar = models.ImageField(upload_to=generate_user_folder_avatar,storage=OverwriteStorage(),validators=[is_square_png],blank=True)

    usertype_choices = [
        ('PR', 'Producer'),
        ('ME', 'Mastering Engineer'),
        ('CP', 'Composer'),
        ('SI', 'Singer'),
        ('AR', 'Artist'),
        ('DJ', 'Disk Jockey'),
        ('LI', 'Listener'),
        ('OT', 'Other'),
    ]

    usertype = models.CharField(max_length=2,
                                 choices=usertype_choices,
                                 default='PR')
    daw_choices = [
        ('FL', 'FL Studio'),
        ('AB', 'Live'),
        ('BT', 'Bitwig Studio'),
        ('CS', 'SONAR X3'),
        ('CB', 'Cubase'),
        ('AP', 'Apple Logic'),
        ('RE', 'Reason'),
        ('SO', 'Sony ACID'),
        ('PR', 'Pro Tools'),
        ('ON', 'Studio One'),
        ('MT', 'Digital Performer'),
        ('SA', 'Samplitude'),
        ('MC', 'Mixcraft'),
        ('RP', 'Reaper'),
        ('AR', 'Ardour'),
        ('OT', 'Other'),
        ('NO', 'None'),
    ]

    daw = models.CharField(max_length=2,choices=daw_choices,default='NO')
    usergenre = models.CharField(max_length=20,blank=True)
    birthday = models.DateField(blank=True)

    joined = models.TimeField(auto_now=True,auto_now_add=False)
    followers = models.ManyToManyField(User, related_name="followers",blank=True)
    status = models.TextField(max_length=300,blank=True)
    pro = models.BooleanField(default=False)

1 个答案:

答案 0 :(得分:1)

在您的模型中将其作为外键from yourapp.forms import UserForm, UserProfileForm def register(request): # Like before, get the request's context. context = RequestContext(request) # A boolean value for telling the template whether the registration was successful. # Set to False initially. Code changes value to True when registration succeeds -- which is optional. registered = False # If it's a HTTP POST, we're interested in processing form data. if request.method == 'POST': # Attempt to grab information from the raw form information. # Note that we make use of both UserForm and UserProfileForm. form = UserForm(data=request.POST, prefix='upf') form2 = UserProfileForm(data=request.POST, prefix='upf') # If the two forms are valid... if form.is_valid() and form2.is_valid(): # Save the user's form data to the database. user_reg = form.save() # Now we hash the password with the set_password method. # Once hashed, we can update the user object. user_reg.set_password(user_reg.password) user_reg.save() # Now sort out the UserProfile instance. # Since we need to set the user attribute ourselves, we set commit=False. # This delays saving the model until we're ready to avoid integrity problems. profile = form2.save(commit=False) profile.user = user_reg # Did the user provide a profile picture? # If so, we need to get it from the input form and put it in the UserProfile model. if 'avatar' in request.FILES: profile.avatar = request.FILES['avatar'] # Now we save the UserProfile model instance. profile.save() # Update our variable to tell the template registration was successful --- which is optional. registered = True # Invalid form or forms - mistakes or something else? # Print problems to the terminal. # They'll also be shown to the user. else: print form.errors, form2.errors # Not a HTTP POST, so we render our form using two ModelForm instances. # These forms will be blank, ready for user input. else: form = UserForm(prefix='upf') form2 = UserProfileForm(prefix='upf') # Render the template depending on the context. return render_to_response( 'profile/register.html', {'form': form, 'form2': form2, 'registered': registered}, context)

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
       //... code
}