سؤال

I'm using Django-Profiles with Django 1.4, and I need a way to unsubscribe a user, so they can stop getting emails.

One of the fields in my UserProfile model is user_type, and I have a USER_TYPES list of choices. To keep users in the system, even if they unsubscribe, I decided to have one of the USER_TYPES be InactiveClient, and I'd include a checkbox like so:

Models.py:

USER_TYPES = (
    ('Editor', 'Editor'),
    ('Reporter', 'Reporter'),
    ('Client', 'Client'),
    ('InactiveClient', 'InactiveClient'),
    ('InactiveReporter', 'InactiveReporter'),
)

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    user_type = models.CharField(max_length=25, choices=USER_TYPES, default='Client')
    ... etc.

forms.py

class UnsubscribeForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UnsubscribeForm, self).__init__(*args, **kwargs)
        try:
            self.initial['email'] = self.instance.user.email
            self.initial['first_name'] = self.instance.user.first_name
            self.initial['last_name'] = self.instance.user.last_name
        except User.DoesNotExist:
            pass
    email = forms.EmailField(label='Primary Email')
    first_name = forms.CharField(label='Editor first name')
    last_name = forms.CharField(label='Editor last name')    
    unsubscribe = forms.BooleanField(label='Unsubscribe from NNS Emails')

    class Meta:
        model = UserProfile
        fields = ['first_name','last_name','email','unsubscribe']

    def save(self, *args, **kwargs):
        u = self.instance.user
        u.email = self.cleaned_data['email']
        u.first_name = self.cleaned_data['first_name']
        u.last_name = self.cleaned_data['last_name']
        if self.unsubscribe:
            u.get_profile().user_type = 'InactiveClient'
        u.save()
        client = super(UnsubscribeForm, self).save(*args,**kwargs)
        return client

Edit: I've added additional code context. if self.unsubscribe: is in save() override. Should that be somewhere else? Thank you.

Edit2: I've tried changing UnsubscribeForm in several ways. Now I get a 404, No User matches the given query. But the view function being called works for other forms, so I'm not sure why?

urls.py

urlpatterns = patterns('',
    url('^client/edit', 'profiles.views.edit_profile',
        {
            'form_class': ClientForm,
            'success_url': '/profiles/client/edit/',
        },
        name='edit_client_profile'),
    url('^unsubscribe', 'profiles.views.edit_profile',
        {
            'form_class': UnsubscribeForm,
            'success_url': '/profiles/client/edit/',
        },
        name='unsubscribe'),
        )

These two urls are calling the same view, just using a different form_class.

Edit3: So I don't know why, but when I removed the trailing slash from the unsubscribe url, the form finally loads. But when I submit the form, I still get an error: 'UnsubscribeForm' object has no attribute 'unsubscribe' If anyone could help me understand why a trailing slash would cause the 404 error (No User matches the given query) I wouldn't mind knowing. But as of now, the form loads, but doesn't submit, and the trace ends on this line of my form:

if self.unsubscribe:
هل كانت مفيدة؟

المحلول

Answering my own question again. On ModelForms, you can add form elements that don't exist in the model, and access the value of those fields by accessing self.cleaned_data['form_element_name'] in the save method.

This is what my save method looks like:

def save(self, *args, **kwargs):
    u = self.instance.user
    p = self.instance.user.get_profile()
    u.email = self.cleaned_data['email']
    u.first_name = self.cleaned_data['first_name']
    u.last_name = self.cleaned_data['last_name']
    if self.cleaned_data['unsubscribe']:
        p.user_type = 'InactiveClient'
    u.save()
    p.save()
    client = super(UnsubscribeForm, self).save(*args,**kwargs)
    return client
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top