Javabean-like get & set on ModelForm

14 views
Skip to first unread message

Kayode Odeyemi

unread,
Oct 9, 2011, 3:00:36 PM10/9/11
to django-users
Hello,

I'm using Django ModelForm on add/edit URLs which are both sharing a single template file. The
code I'm working with is like this:

class WebappAuthorize(models.Model):
    institution_name = models.CharField(max_length=32, help_text="Enter your institution name")
    email = models.CharField(max_length=20, help_text="Example, te...@example.com", default=get_current_user(object(), 'email'))
    institution_logo = models.FileField(upload_to=api.file_upload('files', 'logo'),
        blank=True, help_text="Upload your institution logo")
    institution_url = models.CharField(max_length=50, blank=True, help_text="Example, http://example.com")
    phone = models.IntegerField(null=True, blank=True, help_text="Enter a phone number")
    class Meta:
        db_table = u'authorize'

forms.py
------------
class AuthorizeForm(forms.ModelForm):
    class Meta:
        model = WebappAuthorize

views.py
------------
def get_current_user(request, **kwargs):
    if kwargs['email']:
        # select email from User where
        request_email = User.objects.filter(email=request.user)
        email = request_email.values('email')
        edict = email[0]
        return edict.get('email')

def authorize(request):   
    request_user = User.objects.filter(username=request.user)
    username = request_user.values('username')
    udict = username[0]
    u = str(udict.get('username'))
    context = {'page_title' : 'Authorize your institution'}
   
    consumer_obj = WebappOauthConsumer.objects.filter(user=u) # get user_id from user
    print consumer_obj
   
    c = consumer_obj.values('user_id')
    for i in c:
        if i.get('user_id') == u:
            return redirect('update-authorize-institution', user=u, action='update')
   
    if request.method == 'POST':
        authorize_form = AuthorizeForm(request.POST, request.FILES)
        if authorize_form.is_valid():
            print request.POST
            ckey = consumer.generate(request.POST.get('institution_name', ''))
            if ckey is not None:
                oauthconsumer_model = WebappOauthConsumer()
                oauthconsumer_model.user = User(u)
                oauthconsumer_model.institution_name = WebappAuthorize(request.POST.get(u'institution_name', ''))
                oauthconsumer_model.consumer_key = ckey.get('consumer_key')
                oauthconsumer_model.consumer_secret = ckey.get('consumer_secret')
                oauthconsumer_model.created = int(time.time())
                oauthconsumer_model.changed = int(time.time())
                oauthconsumer_model.save()
                return redirect('update-authorize-institution', user=u, action='update')
        else:
            print authorize_form.errors
           
    else:
        authorize_form = AuthorizeForm()
        context['form'] = authorize_form
        context['action'] = 'new'
        context['consumer'] = consumer_obj.values().order_by('id')
       
        for i in context['consumer']:
            p = i
           
        request.session['consumer'] = p
       
    return render_to_response("webapp/authorize.html", context, context_instance=RC(request))

And the edit view
------------------------

def edit_authorize(request, **kwargs):

    context = {'page_title' : 'Update Authorize your institution'}
    context['user'] = kwargs['user']
    context['action'] = kwargs['action']
   
    print request.session['consumer']
   
    if request.method == 'POST':
        authorize_form = AuthorizeForm(request.POST, request.FILES)
        oauthconsumer_model.changed = date.today()
        oauthconsumer_model.save()
   
    else:
        u = WebappOauthConsumer.objects.get(user=kwargs['user']) # Make sure it returns a single user
        authorize_form = AuthorizeForm(data=request.POST, files=request.FILES, instance=u) # instance of WebAuthorize
        context['form'] = authorize_form   
    return render_to_response("webapp/authorize.html", context, context_instance=RC(request))

In each of these form fields, I want their values to be set on edit. A fix I'm working with at the moment
is to store the values in session variables, then print it on the input value property of each form field in
the template file.

{{ request.session.consumer.institution_name_id}}
<div class="group">
                    <label for="{{ form.institution_name.name }}" class="label">{{ form.institution_name.label }}</label>
                    {% if action == 'update' %}
                        <input class="text_field" type="text" disabled="disabled" name="{{ institution_name_id }}" value="{{ request.session.consumer.institution_name_id }}" />
                    {% else %}
                        <input class="text_field" type="text" name="{{ form.institution_name }}" value="{{ request.session.consumer.institution_name_id }}" />
                    {% endif %}
                    {{ form.institution_name.help_text }}
                </div>
                <div class="group">
                    <label for="{{ form.email.name }}" class="label">{{ form.email.label }}</label>
                    {{ form.email }}
                    {{ form.email.help_text }}
                </div>

For example, on the email field, I want its value prepopulated on edit. I tried using the default field option
on the model, but there's no easy way of getting logged in user outside views.py. To provide a workaround,
I created a function in views.py which takes the request object as argument, then I call the function in
models.py like so:

// in models.py
from webapp.views import get_current_user

email = models.CharField(max_length=20, help_text="Example, te...@example.com", default=get_current_user(object(), 'email'))

But it seems impossible to import views.py into models.py. I'm getting: ImportError: cannot import name get_current_user

Please, how can I get such functionality in my template file.

Thanks

--
Odeyemi 'Kayode O.
http://www.sinati.com. t: @charyorde

Daniel Roseman

unread,
Oct 9, 2011, 3:40:05 PM10/9/11
to django...@googlegroups.com
Aargh. Just aaargh. There are so many things wrong with this code I hardly know where to start. Please, try reading some of the documentation, especially the bit about the uses of `get` vs `filter`.

On Sunday, 9 October 2011 20:00:36 UTC+1, Kayode Odeyemi wrote:
Hello,

I'm using Django ModelForm on add/edit URLs which are both sharing a single template file. The
code I'm working with is like this:

class WebappAuthorize(models.Model):
    institution_name = models.CharField(max_length=32, help_text="Enter your institution name")
    email = models.CharField(max_length=20, help_text="Example, te...@example.com", default=get_current_user(object(), 'email'))

You can't do that. The `default` is either a constant, or a callable that takes no parameters. Passing `object()` as a parameter is nonsense in any case.
 
    institution_logo = models.FileField(upload_to=api.file_upload('files', 'logo'),
        blank=True, help_text="Upload your institution logo")
    institution_url = models.CharField(max_length=50, blank=True, help_text="Example, http://example.com")
    phone = models.IntegerField(null=True, blank=True, help_text="Enter a phone number")
    class Meta:
        db_table = u'authorize'

forms.py
------------
class AuthorizeForm(forms.ModelForm):
    class Meta:
        model = WebappAuthorize

views.py
------------
def get_current_user(request, **kwargs):
    if kwargs['email']:
        # select email from User where
        request_email = User.objects.filter(email=request.user)
        email = request_email.values('email')
        edict = email[0]
        return edict.get('email')

What? The current user is available directly via `request.user`. No need to do another query to get it from request.user, that's just too strange. request.user is *already* a User object, and so you can get the email from request.user.email. I really don't understand this mucking about with `values`.
 

def authorize(request):   
    request_user = User.objects.filter(username=request.user)
    username = request_user.values('username')
    udict = username[0]
    u = str(udict.get('username'))

And again, this is nonsense. The current username is `request.user.username`.
 
    context = {'page_title' : 'Authorize your institution'}
   
    consumer_obj = WebappOauthConsumer.objects.filter(user=u) # get user_id from user

As you've done it above `u` is a string, not a User object. You haven't posted the code of the WebappOauthConsumer object, but unless `user` is a CharField (which I *really* hope it isn't) instead of a ForeignKey to User, this won't work.
 
    print consumer_obj
   
    c = consumer_obj.values('user_id')

Aargh, more mucking about with `filter` and `values`. If you want a single object, use `get`. And to get the user_id from that, you can do `consumer_obj.user_id`. Except of course that you already know the user_id, because you had to give it to your query in the first place... it's the same as `request.user.id`.

 
    for i in c:
        if i.get('user_id') == u:

What? If there's a WebappOauthConsumer object (which you've queried by user) whose user_id is the same as the user_id you used to query it with, then redirect? How can that make sense?
 
            return redirect('update-authorize-institution', user=u, action='update')
   
    if request.method == 'POST':
        authorize_form = AuthorizeForm(request.POST, request.FILES)
        if authorize_form.is_valid():
            print request.POST
            ckey = consumer.generate(request.POST.get('institution_name', ''))
            if ckey is not None:
                oauthconsumer_model = WebappOauthConsumer()
                oauthconsumer_model.user = User(u)
                oauthconsumer_model.institution_name = WebappAuthorize(request.POST.get(u'institution_name', ''))

Don't use values from request.POST, use `authorize_form.cleaned_data`. 
 
                oauthconsumer_model.consumer_key = ckey.get('consumer_key')
                oauthconsumer_model.consumer_secret = ckey.get('consumer_secret')

Oh look, more mucking around with `get`. `consumer.generate` is your own function, which presumably returns a dictionary - so since you know it's going to have the right keys, use ckey['consumer_key'].
 
                oauthconsumer_model.created = int(time.time())
                oauthconsumer_model.changed = int(time.time())

                oauthconsumer_model.save()
                return redirect('update-authorize-institution', user=u, action='update')
        else:
            print authorize_form.errors

Who's going to see those errors if you print them here? Anyway, always avoid the `print` statement as it will cause your server to choke if you accidentally leave it in when you release to production.
 
           
    else:
        authorize_form = AuthorizeForm()
        context['form'] = authorize_form
        context['action'] = 'new'
        context['consumer'] = consumer_obj.values().order_by('id')
       
        for i in context['consumer']:
            p = i
           
        request.session['consumer'] = p

Again, you're looping through a list of one dictionary, then assigning one temporary variable to another. What's the point? Why the `values` call? Why not just:
    context['consumer']  = consumer_obj
    request.session['consumer'] = consumer_obj
especially as you'll have corrected the use of `filter` as I mentioned above.
 
       
    return render_to_response("webapp/authorize.html", context, context_instance=RC(request))

And the edit view
------------------------

def edit_authorize(request, **kwargs):

    context = {'page_title' : 'Update Authorize your institution'}
    context['user'] = kwargs['user']
    context['action'] = kwargs['action']
   
    print request.session['consumer']
   
    if request.method == 'POST':
        authorize_form = AuthorizeForm(request.POST, request.FILES)
        oauthconsumer_model.changed = date.today()
        oauthconsumer_model.save()

You seem to be missing the bit where you actually define oathconsumer_model - presumably the result of calling `authorize_form.save(commit=False)`.
 
   
    else:
        u = WebappOauthConsumer.objects.get(user=kwargs['user']) # Make sure it returns a single user
        authorize_form = AuthorizeForm(data=request.POST, files=request.FILES, instance=u) # instance of WebAuthorize

It seems completely pointless to pass in `request.POST` here, since you know this is not a POST so that dictionary will be empty (as will request.FILES). Plus, as your comment notes, AuthorizeForm needs an instance of WebappAuthorize, not WebappOathConsumer, which is what `u` is.
Well, it's not impossible, but since you're presumably importing models.py into views.py, attempting to do the reverse would create a circular dependency. But as I noted above, this makes no sense in any case.

Please, how can I get such functionality in my template file.


Why don't you just pass the values in `initial` when you instantiate the form?
 
    form = AuthorizeForm(initial={'email': request.user.email, 'institution_name': request.session['institution_name']})

Kayode Odeyemi

unread,
Oct 10, 2011, 1:26:31 PM10/10/11
to django...@googlegroups.com

Lesson learnt
 

def authorize(request):   
    request_user = User.objects.filter(username=request.user)
    username = request_user.values('username')
    udict = username[0]
    u = str(udict.get('username'))

And again, this is nonsense. The current username is `request.user.username`.

Lesson learnt
 
    context = {'page_title' : 'Authorize your institution'}
   
    consumer_obj = WebappOauthConsumer.objects.filter(user=u) # get user_id from user

As you've done it above `u` is a string, not a User object. You haven't posted the code of the WebappOauthConsumer object, but unless `user` is a CharField (which I *really* hope it isn't) instead of a ForeignKey to User, this won't work.

user is a ForeignKey. I can now see that I can use request.user.username. 
 
    print consumer_obj
   
    c = consumer_obj.values('user_id')

Aargh, more mucking about with `filter` and `values`. If you want a single object, use `get`. And to get the user_id from that, you can do `consumer_obj.user_id`. Except of course that you already know the user_id, because you had to give it to your query in the first place... it's the same as `request.user.id`.

Now, this is very much required because consumer_obj is QuerySet.

 
    for i in c:
        if i.get('user_id') == u:

What? If there's a WebappOauthConsumer object (which you've queried by user) whose user_id is the same as the user_id you used to query it with, then redirect? How can that make sense?

Thanks. Changed to:

try:
        if consumer_obj != None:
            return redirect('update-authorize-institution', user=request_user, action='update')
    except TypeError:
        raise Http404('Invalid page requested.')
 
            return redirect('update-authorize-institution', user=u, action='update')
   
    if request.method == 'POST':
        authorize_form = AuthorizeForm(request.POST, request.FILES)
        if authorize_form.is_valid():
            print request.POST
            ckey = consumer.generate(request.POST.get('institution_name', ''))
            if ckey is not None:
                oauthconsumer_model = WebappOauthConsumer()
                oauthconsumer_model.user = User(u)
                oauthconsumer_model.institution_name = WebappAuthorize(request.POST.get(u'institution_name', ''))

Don't use values from request.POST, use `authorize_form.cleaned_data`. 

Lesson learnt
 
                oauthconsumer_model.consumer_key = ckey.get('consumer_key')
                oauthconsumer_model.consumer_secret = ckey.get('consumer_secret')

Oh look, more mucking around with `get`. `consumer.generate` is your own function, which presumably returns a dictionary - so since you know it's going to have the right keys, use ckey['consumer_key'].

ckey['consumer_key'] does not work. It's a dict. I can remember accessing a dict like that. I tried it but I did not document the error it returned. I'm on Py2.7
 
                oauthconsumer_model.created = int(time.time())
                oauthconsumer_model.changed = int(time.time())

                oauthconsumer_model.save()
                return redirect('update-authorize-institution', user=u, action='update')
        else:
            print authorize_form.errors

Who's going to see those errors if you print them here? Anyway, always avoid the `print` statement as it will cause your server to choke if you accidentally leave it in when you release to production.

ok. 
 
           
    else:
        authorize_form = AuthorizeForm()
        context['form'] = authorize_form
        context['action'] = 'new'
        context['consumer'] = consumer_obj.values().order_by('id')
       
        for i in context['consumer']:
            p = i
           
        request.session['consumer'] = p

Again, you're looping through a list of one dictionary, then assigning one temporary variable to another. What's the point? Why the `values` call? Why not just:
    context['consumer']  = consumer_obj
    request.session['consumer'] = consumer_obj
especially as you'll have corrected the use of `filter` as I mentioned above.

Firstly, I want to be able to access consumer_obj in the template file simply like this: consumer.institution_name for example. I don't want to have to loop through the session object. I'm looping through because context['consumer']  = consumer_obj returns a list and I need it as dict.

Though I was trying to do something like this:

p = dict((i for i in context['consumer']))

Some one-liner. But I guess I'm not an expert yet.
 
       
    return render_to_response("webapp/authorize.html", context, context_instance=RC(request))

And the edit view
------------------------

def edit_authorize(request, **kwargs):

    context = {'page_title' : 'Update Authorize your institution'}
    context['user'] = kwargs['user']
    context['action'] = kwargs['action']
   
    print request.session['consumer']
   
    if request.method == 'POST':
        authorize_form = AuthorizeForm(request.POST, request.FILES)
        oauthconsumer_model.changed = date.today()
        oauthconsumer_model.save()

You seem to be missing the bit where you actually define oathconsumer_model - presumably the result of calling `authorize_form.save(commit=False)`.

Yes. Code updated. By the way, I think it is appropriate to use the session object here instead of a new instance of  oauthconsumer_model right? I know on Google App Engine, this will be very costly.
 
   
    else:
        u = WebappOauthConsumer.objects.get(user=kwargs['user']) # Make sure it returns a single user
        authorize_form = AuthorizeForm(data=request.POST, files=request.FILES, instance=u) # instance of WebAuthorize

It seems completely pointless to pass in `request.POST` here, since you know this is not a POST so that dictionary will be empty (as will request.FILES). Plus, as your comment notes, AuthorizeForm needs an instance of WebappAuthorize, not WebappOathConsumer, which is what `u` is.

Yes! haven't perfected this view callback. Thanks

Thank you. This is exactly what I need. Is this the same as bounding a form? If I bind the form to its values, will it have the same result?

Thanks for taking time to look into the code.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/sRLqe8IkbBMJ.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Reply all
Reply to author
Forward
0 new messages