web-dev-qa-db-fra.com

Django ForeignKey Model ou AdminModel?

Comment puis-je définir une valeur par défaut sur un champ ForeignKey dans un modèle Django ou AdminModel?

Quelque chose comme ça (mais bien sur ça ne marche pas) ...

created_by = models.ForeignKey(User, default=request.user)

Je sais que je peux «tromper» dans la vue, mais en ce qui concerne AdminModel, cela ne semble pas possible.

20
T. Stone
class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, default=lambda: Foo.objects.get(id=1) )
30
Daniel Magnusson

Voici une solution qui fonctionnera dans Django 1.7. Au lieu de fournir la valeur par défaut à la définition du champ, définissez-la comme pouvant être annulée, mais remplacez la fonction 'save' pour la remplir pour la première fois (tant qu'elle est nulle):

class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, null=True)

    def save(self, *args, **kwargs):
        if self.a is None:  # Set default reference
            self.a = Foo.objects.get(id=1)
        super(Bar, self).save(*args, **kwargs)
10
o_c

Pour Django 1.7 ou supérieur,

Créez simplement un objet ForeignKey et enregistrez-le. La valeur "default" peut être l'id de l'objet à lier par défaut.

Par exemple,

created_by = models.ForeignKey(User, default=1)
6

Si vous utilisez la version de développement de Django, vous pouvez implémenter la méthode formfield_for_foreignkey() sur votre AdminModel pour définir une valeur par défaut.

5
Steef

J'ai fait la même chose que @o_c, mais je préférerais utiliser get_or_create plutôt que simplement pk.

class UserSettings(models.Model):
    name = models.CharField(max_length=64, unique=True)
    # ... some other fields 

    @staticmethod
    def get_default_user_settings():
        user_settings, created = UserSettings.objects.get_or_create(
            name = 'Default settings'
        )
        return user_settings

class SiteUser(...):
    # ... some other fields

    user_settings = models.ForeignKey(
        to=UserSettings, 
        on_delete=models.SET_NULL, 
        null=True
    )

    def save(self, *args, **kwargs):
        if self.user_settings is None:
            self.user_settings = UserSettings.get_default_params()
        super(SiteUser, self).save(*args, **kwargs)
3
Max Malysh
def get_user_default_id():
    return 1

created_by = models.ForeignKey(User, default=get_user_default_id)
1
Philippos

Quant à moi, pour Django 1.7 son travail, juste pk:

category = models.ForeignKey(Category, editable=False, default=1)

mais rappelez-vous que la migration ressemble à

migrations.AlterField(
            model_name='item',
            name='category',
            field=models.ForeignKey(default=1, editable=False, to='item.Category'),
            preserve_default=True,
        ),

donc, je ne pense pas que cela fonctionne avec un utilisateur dynamique pk.

1
LennyLip

Pour Django> = 1.7, vous pouvez définir la valeur par défaut pour un champ ForeignKey de deux manières différentes:

1) directement sous forme d'entier

DEFAULT_CREATED_BY_USER = 42

class MyModel(Model):
    created_by = models.ForeignKey(User, default=DEFAULT_CREATED_BY_USER)

2) En tant qu'appel non lambda renvoyant un entier

Vous pouvez également utiliser un appelable pouvant être résolu en un chemin de module complet. Cela signifie que lambdas ne fonctionne pas. Mais cela va:

def default_created_by_user():
    return 42

class MyModel(Model):
    created_by = models.ForeignKey(User, default=default_created_by_user)

Références:

1
Rune Kaagaard

Ceci est une légère modification de la réponse de o_c . Cela devrait vous sauver un coup sur la base de données. Notez que dans la méthode save, j'utilise self.a_id = 1 au lieu de self.a = Foo.objects.get (id = 1). Cela a le même effet sans avoir à interroger Foo.

class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, null=True)

    def save(self, *args, **kwargs):
        if self.a is None:  # Set default reference
            self.a_id = 1
        super(Bar, self).save(*args, **kwargs)
1
Andrew Simpson

Au lieu de la fonction lambda, utilisez une fonction partielle. La fonction Lambda n’est pas une sérialisation et donne donc une erreur dans les migrations.

class Foo(models.Model):
    a = models.CharField(max_length=42)

class Bar(models.Model):
    b = models.CharField(max_length=42)
    a = models.ForeignKey(Foo, default=partial(Foo.objects.get, id=1 ))
0
Kedar Jathar

Vous devez avoir les paramètres liés à setting.AUTH_USER_MODEL dans le fichier settings.py.

Vous pouvez regarder dans le document ci-dessous:

" https://docs.djangoproject.com/fr/1.10/topics/auth/customizing/#substituting-a-custom-user-model "

0
vikasvmads

Vous pouvez remplacer la méthode get_form de votre administrateur de modèle.

admin.py

class YourModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(YourModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['created_by'].initial = request.user
    return form

admin.site.register(YourModel, YourModelAdmin)
0
Anusha Prasanth