Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django related models and UpdateView fields

I created a model (UserSettings) to extend django's User model through a OneToOneField (as recommended by the documentation):

class UserSettings(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    subscribeToMails = models.BooleanField(default=True)
    [...]

I wish to offer my users a way to edit some of their profile data, some of which is stored in the User model (the email address), and the rest in the UserSettings model. How may I do that?

I thought of two ways: adding another OneToOneField in the UserSettings model for the email address field; or overriding the UpdateView get_queryset() method (but I'm not sure how). Is there a best or recommended way to do it? So far here's how my view look:

class EditUser(UpdateView):
    model = UserSettings
    fields = ('emailVisible', 'subscribeToMails', 'mpPopupNotif',
              'mpEmailNotif', 'avatar', 'quote', 'website')
    template_name = 'user/edit.html'

    def get_object(self):
        return UserSettings.objects.get(user_id=self.request.user)

    def get_success_url(self):
        return reverse_lazy('user:edit')
like image 894
Thomas Maurin Avatar asked Dec 19 '25 03:12

Thomas Maurin


1 Answers

Thanks for the replies! However, since I couldn't figure out how to make this work and thought using two tables eventually resulted in too much clutter to my taste, I finally went with the easier route and subclassed AbstractUser:

# models.py
class ForumUser(AbstractUser):
    subscribeToMails = models.BooleanField(default=True)
    [...]

# views.py
class EditUser(LoginRequiredMixin, UpdateView):
    model = ForumUser
    fields = ('email', 'emailVisible', 'subscribeToMails', 'mpPopupNotif',
              'mpEmailNotif', 'avatar', 'quote', 'website')
    template_name = 'user/edit.html'
    success_url = reverse_lazy('forum:welcome')

    def get_object(self):
        return ForumUser.objects.get(username=self.request.user)

I only had to change my registration form:

# forms.py
class RegisterForm(UserCreationForm):
    email = forms.EmailField(required=True)

    class Meta:
        model = ForumUser
        fields = ('username', 'email', 'password1', 'password2')

    def clean_email(self):
        "Ensure registered emails are unique."
        email = self.cleaned_data.get('email')
        username = self.cleaned_data.get('username')
        if email and ForumUser.objects.filter(email=email).exclude(
                username=username).count():
            raise forms.ValidationError('Email address already in use.')
        return email

    def clean_username(self):
        """
        UserCreationForm method where mentions of the User model are replaced
        by the custom AbstractUser model (here, ForumUser).
        https://code.djangoproject.com/ticket/19353#no1
        and https://docs.djangoproject.com/en/1.7/_modules/django/contrib/
        auth/forms/#UserCreationForm
        """
        username = self.cleaned_data["username"]
        try:
            ForumUser.objects.get(username=username)
        except ForumUser.DoesNotExist:
            return username
        raise forms.ValidationError(
            self.error_messages['duplicate_username'],
            code='duplicate_username',
        )
like image 150
Thomas Maurin Avatar answered Dec 21 '25 18:12

Thomas Maurin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!