简体   繁体   中英

can't pre-populate a django database

so I've been following this guide from Django 1.1 but I'm actually using Django 2 for how to pre-populate Django database I'm using SQLite database and this is my code with Faker library but it just won't run when I want to run it in the CMD. Please help me if you can:

This is my first file which is the script for populating the database: (populate_first_app.py)

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings')

import django
django.setup()

## FAKE POPULATION SCRIPT:

import random
from first_app.models import AccessRecord,Webpage,Topic
from faker import Faker

# Creating a fake generator:
fakegen = Faker()
topics = 

['Search', 'Social', 'Marketplace', 'News', 'Games']
def add_topic():
    t = Topic.objects.get_or_create(top_name=random.choice(topics))[0]
    t.save()
    return t

def populate(N = 5):

for entry in range(N):

    # GET THE TOPIC FOR THE ENTRY:
    top = add_topic()

    # Create the fake data for that entry:
    fake_url = fakegen.url()
    fake_date = fakegen.date()
    fake_name = fakegen.company()

    # Create the new webpage entry:
    webpg = Webpage.objects.get_or_create(topic = top, url = fake_url, name = fake_name)[0]

    # Create a fake access record for that webpage
    acc_rec = AccessRecord.get_or_create(name = webpg, date = fake_date)[0]

    if __name__ == '__main__':
        print("Populating Script!")
        populate(20)
        print("Populating Complete!")

And finally, this is my models.py file of the only app I have in this project:

    from django.db import models

class Topic(models.Model):
    top_name = models.CharField(max_length = 255, unique = True)


    def __str__(self):
        return self.top_name

class Webpage(models.Model):
    # A Foreign key is grabbed from another table
    topic = models.ForeignKey(Topic, on_delete=None)
    name = models.CharField(max_length=264, unique=True)
    url = models.URLField(unique=True)

    def __str__(self):
        return self.name

class AccessRecord(models.Model):
    name = models.ForeignKey(Webpage, on_delete=None)
    date = models.DateField()

    def __str__(self):
        # we cast it into string because self.date is a date object
        return str(self.date)

I did go through your code and I found the problem why Django not creating the fake data. You have indented the main function in your "populate_first_app.py". Remove the indentation and your code should work fine.

If statement indentation wrong , nothing else

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'first_project.settings')

import django
django.setup()

## FAKE POPULATION SCRIPT:

import random
from first_app.models import AccessRecord,Webpage,Topic
from faker import Faker

# Creating a fake generator:
fakegen = Faker()
topics = 

['Search', 'Social', 'Marketplace', 'News', 'Games']
def add_topic():
    t = Topic.objects.get_or_create(top_name=random.choice(topics))[0]
    t.save()
    return t

def populate(N = 5):

for entry in range(N):

    # GET THE TOPIC FOR THE ENTRY:
    top = add_topic()

    # Create the fake data for that entry:
    fake_url = fakegen.url()
    fake_date = fakegen.date()
    fake_name = fakegen.company()

    # Create the new webpage entry:
    webpg = Webpage.objects.get_or_create(topic = top, url = fake_url, name = fake_name)[0]

    # Create a fake access record for that webpage
    acc_rec = AccessRecord.get_or_create(name = webpg, date = fake_date)[0]

if __name__ == '__main__':
   print("Populating Script!")
   populate(20)
   print("Populating Complete!")

It isn't absolutely clear what your issue is without an error message, but my hunch is that you are failing to bootstrap the Django environment in your standalone script.

Django has a special facility for building "Commands" that you can run within the Django environment, without having to "set it up" as you are doing in populate_first_app.py.

Django Documentation for Custom Commands

In your example above, you would want to move "populate_first_app.py" to be located at "first_app/management/commands/populate_first_app.py". Then you need to place your function within the BaseCommand:

from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll
# .. other imports
class Command(BaseCommand):
   help = 'Populates test data in first_app'

   def add_arguments(self, parser):
      parser.add_argument('n', type=int)

   def handle(self, *args, **options):
      fakegen = Faker()
      for entry in range(args.n):
          #.. generate each entry

Once you have this command you can then run it from manage.py:

manage.py populate_first_app -n 20

The bonus is that when someone else wants to use this, they can see it when they run

manage.py help

first you need to do python manage.py migrate

and then respectively python manage.py makemigrations

then give some suggestion like that... AccessRecort change to AccessRecord [y/N]? press y

then python mange.py migrate

Operations to perform: Apply all migrations: admin, auth, contenttypes, first_app, sessions Running migrations: Applying first_app.0002_auto_20190731_1445... OK

(MyDjangoEnv) C:\your\file\path\first_project>python populate_first_app.py

Populating Script!

Populating complete!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM