Je suis nouveau sur django, je souhaite modifier mes modèles (qui sont déjà dans ma base de données sqlite3) sans buger tout mon projet. La dernière fois que j'ai modifié mes modèles, il m'a fallu des heures pour le réparer car j'ai buggé tout le projet. Donc, je ne veux pas faire la même erreur, pourriez-vous m'aider avec les commandes s'il vous plaît? Merci pour ton aide

Models.py (en ce moment)

from django.db import models

THE_GENDER = [
    ("Monsieur", "Monsieur"),
    ("Madame", "Madame")
]


class Post(models.Model):


    name = models.CharField(max_length=100)
    email = models.CharField(max_length=100)
    gender = models.CharField(max_length=8, choices=THE_GENDER)
    number = models.CharField(max_length=100)


    def __str__(self):
        return self.name

La modification que je veux apporter aux modèles (je veux ajouter un utilisateur auteur dans les modèles. Je sais donc qui fait le formulaire.)

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

THE_GENDER = [
    ("Monsieur", "Monsieur"),
    ("Madame", "Madame")
]


class Post(models.Model):


    name = models.CharField(max_length=100)
    email = models.CharField(max_length=100)
    gender = models.CharField(max_length=8, choices=THE_GENDER)
    number = models.CharField(max_length=100)
    author = models.ForeignKey(User, on_delete=models.CASCADE)


    def __str__(self):
        return self.name

Mes fichiers admin.py (pas sûr si je n'ai pas besoin de le laisser le même ou de le modifier)

from django.contrib import admin
from .models import Post

admin.site.register(Post)

Mes fichiers forms.py

from django import forms
from .models import Post
from crispy_forms.helper import FormHelper


class post_form(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(post_form, self).__init__(*args, **kwargs)

        self.helper = FormHelper(self)

    class Meta:
        model = Post
        fields = ["name", "email", "gender", "number"]


Views.py

from django.shortcuts import render
from django.http import HttpResponse
from .forms import post_form


# Create your views here.
def home(request):
    form = post_form(request.POST or None)
    if form.is_valid():
        form.save()

    context = {
        "form": form
    }


    return render(request, "sms/home.html", context)
2
tiberhockey 12 févr. 2020 à 18:22

3 réponses

Vous pouvez gérer ce problème de différentes manières.

S'il n'y a pas de données, vous pouvez facilement ajouter le nouveau champ et exécuter vos migrations. Tu devrais aller bien

Si vous avez déjà des publications, vous pouvez autoriser le champ à être annulé, puis exécuter vos migrations avant d'aller le remplir.

Une manière plus intuitive de le faire, surtout si vous disposez déjà de données, consiste à affecter un utilisateur à la publication lors de l'exécution des migrations.

Créez d'abord une migration avec le champ auteur autorisé à être nul, puis

author = models.ForeignKey(User, null=True, on_delete=models.CASCADE)

Manage.py makemigrations manage.py migrate

Après cela, supprimez l'attribut null.

author = models.ForeignKey(User, on_delete=models.CASCADE)

manage.py makemigrations

Ouvrez le fichier de migration maintenant généré qui sera que vous modifierez avec une méthode personnalisée comme ci-dessous et exécutez migrate après cela.

from django.db import migrations, models


# create custom method
def add_author(apps, schema_editor):
    User = apps.get_model('auth', 'User')  
    Post = apps.get_model('something', 'Post')  
    posts = Post.objects.all()
    author = User.object.get(id=1) # whichever user you want to use as the author
    for post in posts:
        post.author = author
        post.save()

class Migration(migrations.Migration):

    dependencies = [
        ('posts', '00000000'),
    ]

    operations = [
        migrations.RunPython(add_author), # this will run the method above
        migrations.AlterField(
            model_name='post',
            name='author',
            field=models.ForeignKeyField...,
        ),

    ]

Consultez ce lien pour une explication plus détaillée de la façon dont cela travaux

0
Bernard 'Beta Berlin' Parah 12 févr. 2020 à 16:19

Vous devez d'abord modifier votre models.py

# models.py
class Post(models.Model):
    name = models.CharField(max_length=100)
    email = models.CharField(max_length=100)
    gender = models.CharField(max_length=8, choices=THE_GENDER)
    number = models.CharField(max_length=100)
    author = models.ForeignKey(User, on_delete=models.CASCADE) # add new field

    def __str__(self):
        return self.name

Comme vous avez ajouté un nouveau champ author , vous devez exécuter makemigrations puis la commande migrate .
Lors des migrations, il peut vous être demandé de fournir une valeur par défaut pour le champ author pour les instances Post existantes . Pendant ce temps, vous pouvez fournir des valeurs "interactivement" via le shell Django . Toute PK instance User valide sera une entrée valide pendant la durée. Pour info: il s'agit d'un processus ponctuel

Après cela, modifiez votre home(...) vue,

from django.contrib.auth.decorators import login_required


@login_required
def home(request):
    form = post_form(request.POST or None)
    if form.is_valid():
        instance = form.save(commit=False)
        instance.auther = request.user
        instance.save()

    context = {
        "form": form
    }

    return render(request, "sms/home.html", context)

Remarque: vous devez utiliser @login_required(...) décorateur pour obtenir l'utilisateur authentifié dans request.user attribut.

1
Arakkal Abu 12 févr. 2020 à 16:09

Votre migration est délicate, car vous voulez que chaque publication soit liée à un utilisateur. Pour contourner ce problème, vous pouvez procéder comme suit:

Ajoutez votre nouveau champ avec null=True models.ForeignKey(User, on_delete=models.CASCADE, null=True) puis manage.py makemigrations alors vous devez décider quoi faire. Soit (1) ajoutez des auteurs à vos articles existants à la main, soit (2) supprimez-les tous

manage.py shell
from x.models import Post
from django.contrib.auth.models import User

# 1
user = User.objects.get(id=1) # get your user
Post.objects.all().update(author=user)

# or 2
Post.objects.all().delete()

Vous pouvez enfin définir vos auteurs comme vous le souhaitez: models.ForeignKey(User, on_delete=models.CASCADE) encore manage.py makemigrations

Voir les commentaires pour plus d'informations

0
ChrisRob 12 févr. 2020 à 16:03