Django models with OneToOne relationships?

前端 未结 3 1009
南旧
南旧 2021-02-09 12:21

Let\'s say I\'m using the default auth.models.User plus my custom Profile and Address models which look like this:

class P         


        
相关标签:
3条回答
  • 2021-02-09 12:40

    What about using 3 separate ModelForm. One for Address, one for User, and one for Profile but with :

    class ProfileForm(ModelForm):
      class Meta:
        model = Profile
        exclude = ('user', 'address',)
    

    Then, process these 3 forms separately in your views. Specifically, for the ProfileForm use save with commit=False to update user and address field on the instance :

    # ...
    profile_form = ProfileForm(request.POST)
    if profile_form.is_valid():
      profile = profile_form.save(commit=False)
      # `user` and `address` have been created previously
      # by saving the other forms
      profile.user = user
      profile.address = address
    

    Don't hesitate to use transactions here to be sure rows get inserted only when the 3 forms are valid.

    0 讨论(0)
  • 2021-02-09 13:04

    I think your are looking for inline formsets with model forms. This helps you to deal with multiple forms on one page and also takes care of foreign key relations.

    Update:

    Maybe this question helps you too: Django: multiple models in one template using forms

    0 讨论(0)
  • 2021-02-09 13:06

    You should look into the officially recommended way to extend the User model first, as seen in the docs, which I believe comes directly from the project manager's personal blog about the subject. (The actual blog article is rather old, now)

    As for your actual issue with forms, have a look at the project manager's own reusable django-profiles app and see if perusing the code solves your issue. Specifically these functions and the views in which they are utilized.

    Edited to Add:

    I've looked into it a bit (as I needed to do so myself). It seems something like so would be sufficient:

    # apps.profiles.models
    
    from django.db import models
    from django.contrib.auth.models import User
    
    class UserProfile(models.Model):
        user = models.ForeignKey(User, unique=True)
        ...
        birth_date = models.DateField(blank=True, null=True)
        joined = models.DateTimeField(auto_now_add=True)
        modified = models.DateTimeField(auto_now=True)
    
        class Meta:
            verbose_name = 'user profile'
            verbose_name_plural = 'user profiles'
            db_table = 'user_profiles'
    
    class Address(models.Model):
        user = models.ForeignKey(UserProfile)
        ...
    
    # apps.profiles.forms
    
    from django import forms
    from django.forms import ModelForm
    from django.forms.models import inlineformset_factory
    from django.contrib.auth.models import User
    from apps.profiles.models import UserProfile, Address
    
    class UserForm(ModelForm):
        class Meta:
            model = User
            ...
    
    class UserProfileForm(ModelForm):
        class Meta:
            model = UserProfile
            ...
    
    AddressFormSet = inlineformset_factory(UserProfile, Address)
    

    I was using "..." to snip content in the code above. I have not yet tested this out but from looking through examples and the documentation on forms I believe this to be correct.

    Note I put the FK from the Address model to the UserProfile and not the other way around, as in your question. I believe the inline formsets need this to work correctly.

    Then of course in your views and templates you will end up treating UserForm, UserProfileForm, and AddressFormSet separately but they can all be inserted into the same form.

    0 讨论(0)
提交回复
热议问题