2024-01-07

Goal

Learn how to upload more than 100 records via the shell

Notes

Last time I left off, I wanted to learn how to Django Bulk Upload to upload a variety of data features (including fighter cosmetics and spirit fighter stats). I was still running into the bizzare "non-unique id" error that I was last time.

I ended up screwing up my Database Migrations and needed to reset my SQLlite database. That's not a big deal here because I had no important data in the app (with the exception of the Django Superuser) which was easy to recreate using

python manage.py createsuperuser

I still wanted to use some kind of bulk upload system, so I referenced ChatGPT for help.

It wasn't helpful, but I was able to increase the batch size to 2500 (since there are only about ~2200 fighters I have data for).

Bizarrely enough, this approach worked. Instead of using the batching procedure, I therefore decided to just use the following script:

from fighters.models import SpiritFighter
import json

with open(r"C:\Users\Billy\Documents\HitHub\bulk_uploads\Fighters\spirit_fighter_metadata.json", "r") as f:
    spirit_fighter_data = json.load(f)

# Clear the current table
SpiritFighter.objects.all().delete()

# Build up the objects data
objs = []
for fighter_id, fighter_data in spirit_fighter_data.items():
    objs.append(SpiritFighter(
        ufc_id = fighter_id,
        height = fighter_data["height"],
        weight = fighter_data["weight"],
        stance = fighter_data["stance"],
        first_name = fighter_data["first_name"],
        last_name = fighter_data["last_name"],
        nickname = fighter_data["nickname"],
        date_of_birth = fighter_data["DOB"],
        w = fighter_data["w"],
        l = fighter_data["l"],
        d = fighter_data["d"],
        stats = fighter_data["stats"],
    ))

SpiritFighter.objects.bulk_create(objs)

to simply bulk create all of the objects at once. This gave no issues and when I tried removing the table clear at the beginning (SpiritFighter.objects.all().delete()) it was still effective. I must have been entering it in an incorrect way or maybe somehow there was some kind of issue with Asynchronous allocation of unique Primary Keys.

Designing the Bets Table

This is the tricky one that I've been putting off for a while. I now have the key components for the rest of the app and know how to bulk upload records (which will become important later on for actually populating my database with tables.). The last model I'll need to design will be for the Bets App. I'm thinking that

  • Bets will need to be placed in advance, so they should be tied to Upcoming Fights in the Fights App via that fight's id
  • Some bets will be reliant on different conditionals that will need to reference the behavior of the individual fighter (i.e tied to a fighter_id from the Fights App)
  • I want to implement two bets for sure, moneyline and totals bets, however prop bets will be the most fun. Either way a the Bets App should have a unique model
    • moneyline - Which fighter will win
    • totals - How long will the fight last

I wanted to create something dynamic that had a basic structure that all other bets conditionals could be stacked on top of. In this case ChatGPT actually had a great solution that involved building a general Bet class that other bet types could be stacked on top of. It included the class Meta field with abstract = True, which was so that a Django wouldn't build a table for the base bet class but instead will build one for other bet types (i.e moneyline and totals bets).

With the help of ChatGPT I was able to create these classes and generate the Bets table. Nice! Now I'll be able to create additional prop bets (i.e touchgloves, makes weight, gets murdered, etc.) easily in the future.

Designing the CustomUser

That was a hell of a journey but I finally have the bare bones of what I need to get the app off the ground on the data side. Of course we can make adjustments as needed (adding or removing features). I found out I was on the old fixed-routes branch when I used the

git branch --show-current

command. The last thing I wanted to do was adjust the Accounts App to use a custom user model. Thankfully this is covered in Django For Professionals on pg 56 so following the instructions was easy enough. The author notes just how important it is to create a custom user model since everything else is tied into the app.

To do this I needed to create a CustomUser model in the Accounts App based on Django's built in AbstractUser model. Then I needed to add that into my project's hithub/settings.py file and set the default user to

AUTH_USER_MODEL = "accounts.CustomUser"

so that Django recognizes it as the default user.

Thankfully I did this before any important info was loaded into the app because there were some serious migration conflicts with my test superuser! Thankfully I was able to wipe the database by deleting SQLlite and the non-initial migrations of each app. I also added the coin attribute to this custom user to allow our users to use money.

Pushing Changes to GitHub

Now that all of the Database stuff was up and ready to go and my custom users were running all I needed to do was push it to GitHub. I checked out a Git Branch called completed-db-construction via the following command and pushed to GitHub:

git checkout -b completed-db-construction
git add .
git commit -m "my inspiring message"
git push

Then I pushed these changes to Staging by merging it with the dev branch.

Finally I merged dev to main and pulled it back into my local project with git pull.

Also last minute I decided to declare the currency to be hitcoin. That was a very important last minute change.

Results

  • Finished developing the Database needed for the HitHub App
    • Completed functionality to handle basic bets within the Bets App
    • Added a sponsor where a user can sponsor a fighter in the Fighters App
      • This will come in handy if I decide to assign users their own fighter to take care of in the future
  • Implemented a CustomUser model for the Accounts App
    • Now users have 1k starting hitcoin

Next Time

  • Learn how to bulk upload other attributes
    • Learn how to bulk upload cosmetics
  • Learn how to create fighters in the database based on the data we've bulk uploaded
  • It may make sense to use AWS Lambda functions to execute the actual fights. Therefore it might make a sense to learn how to integrate the Django API
  • Start developing the Frontend / surfacing data to the Front end
  • Write Unit Tests D:

Previous Note 2024-01-03 Next Note 2024-01-08