0

I have this small models.py file:

models.py

# -*- coding: utf-8 -*-
import datetime

from django.db import models
from django.contrib.auth.models import User

from apps.strumento.models import Strumento, Veicolo

class AllegatoStrumento(models.Model):
    allegato = models.FileField(upload_to='uploads_strumento/', blank=True, null=True)
    data_creazione = models.DateTimeField(default=datetime.datetime.now)
    creatore = models.ForeignKey(User)
    strumento = models.ForeignKey(Strumento)

    class Meta:
        verbose_name_plural = "Allegati strumenti"
        verbose_name = "Allegato strumento"

    def __unicode__(self):
        return str(self.allegato)

I would like the 'creatore' field to be automatically populated with the logged user triggering the save/update action, so that I can display it but not allow it to be altered directly.

OF course, just putting the User FK like this in the model, it asks me which user to put in, which I don't want to happen.

I've tried with both these lines:

creatore = models.ForeignKey(User, default=request.user.get_username())
creatore = models.ForeignKey(User, default=User.get_username())

but none of them work, as the first misses an instance of request while the second complains that the method is NOT (corrected, thanks @bruno desthuilliers) being called on an instance ("TypeError: unbound method get_username() must be called with User instance as first argument (got nothing instead)")

What could an easy way for doing that be?

Seether
  • 1,524
  • 1
  • 14
  • 28
  • possible duplicate of [How to assign currently logged in user as default value for a model field?](http://stackoverflow.com/questions/2414473/how-to-assign-currently-logged-in-user-as-default-value-for-a-model-field) – bruno desthuilliers Oct 30 '14 at 12:05

1 Answers1

0

The fact that models don't have a "magical" access to the "current request" is by design - because there's not necessarily such a thing as a "current request", ie when working on your models from a command-line script etc.

The correct way to handle the problem is to explicitely pass in the "current user" from your views (which get the request as first argument).

As a side note

  1. your implementation of AllegatoStrumento.__unicode__ is broken (__unicode__ must return a unicode object, not a str object - hint: all text fields in django models return unicode)

  2. your second attempt at providing a default in the model itself complains that get_username() is not called on an instance

  3. anyway, your field expects a User instance, not a username so the call to get_username() is way off mark.

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • Ok, so I'll have to deal with the views. As I'm working with the admin module, it means I'll have to extend some admin view. I'll see what I can do, thanks. About the other points: 1) Maybe "return unicode(self.allegato).encode('utf-8')" works better? 2) My lapsus. I intended exactly the same thing you stated. 3) That's true, this was more of a test to see if I could handle User some way. In fact, putting the username as a reference to a user wasn't in my plans at all, as it would hardly be a great idea anyways. – Seether Oct 30 '14 at 14:03
  • There's an exemple about how to handle this in the admin here http://stackoverflow.com/a/2414725/41316. About the `__unicode__` method, `self.allegato` is _already_ a unicode object so there' notthing more to do than `return self.allegato`. FWIW, encoding it as utf8 would make it a string (a utf-8 encoded string) again, not unicode... – bruno desthuilliers Oct 30 '14 at 14:09
  • Yes, I was reading that link right now indeed, thank you. As per the unicode issue, I think I used to have problems with the representation of objects (having "object" printed out instead of a readable name and such), and putting a str as return object seemed to be working. I'll think back and try to do it properly. Unfortunately I'm new to both python and django, so the way is a bit hard right now. Still, thanks for pointing out. – Seether Oct 30 '14 at 14:15
  • oops sorry, I just noticed `allegrato` was a `FileField`. So what you want is `return unicode(self.allegato)` (or `return u"%s" % self.allegato`). The point is to return a _unicode_ string (`unicode` type), not a byte string (`str` type). – bruno desthuilliers Oct 30 '14 at 14:24
  • Ah ok, that makes more sense now. I had already chosen unicode(self.allegato) anyway, and I will fix all similiar errors through my project the same way. Thanks. – Seether Oct 30 '14 at 14:31
  • As a side note, the method here: http://stackoverflow.com/a/2414725/41316 doesn't seem to work for me on inlines models... It simply gets ignored. Guess I'll have to investigate more. – Seether Oct 30 '14 at 14:33
  • Nope it wont work for inlines indeed - but browsing the doc (and possibly the source code) you should find out. – bruno desthuilliers Oct 30 '14 at 15:02
  • Indeed. And done already: http://stackoverflow.com/questions/1574313/working-with-extra-fields-in-an-inline-form-save-model-save-formset-cant-ma – Seether Oct 30 '14 at 15:04