How can i fill django model from external API? - python

I have a model for movies in my django project:
class Movie(models.Model):
title = models.CharField(max_length=128, blank=False)
description = models.TextField()
movie_length = models.CharField(max_length=20)
director = models.CharField(max_length=50)
rating = models.FloatField(validators=[MinValueValidator(0.0),MaxValueValidator(10.0)])
created_at = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='movie_img/')
category = models.CharField(max_length=50)
I want to fill the database using python API wrappers for themoviedb.org API like this https://github.com/celiao/tmdbsimple/ or https://github.com/wagnerrp/pytmdb3/. But i am not sure how to do this. I just want to put around 100 movies at one go without having to add every movie one by one.
How can i do this, please help.
Thank you.

First you will have to read the data from the API into Python objects. Assume you now have a list L of tuples, each tuple is a record of a movie.
Your script could be load_from_api.py
#!/usr/bin/env python
import os
import sys
# ... read the data from the API
# ... so L = [("movie title","movie description..."),("movie2 title",..)]
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
os.environ["DJANGO_SETTINGS_MODULE"] = "mysite.settings"
import django
django.setup()
from yourapp.models import Movie
for movie in L:
m = Movie(title=movie[0],
description=movie[1],
...
)
m.save()
Then simply run the script.
Note that you could load the data directly to the DB with SQL, but that is not recommended since this ignores the django models rules, defaults, validations, signals etc.

Related

Find table by name - Django

How I can find table by name in code python?
Example:
class AlexAlex(models.Model):
title = models.CharField(max_length=255)
message = models.TextField()
dataMsg = models.DateField()
fromMsg = models.CharField(max_length=255)
readMsg = models.BooleanField(default=False)
def __str__(self):
return self.title
and now I want to find the class name as it has some username.
Example in code:
UserLogged = "AlexAlex" or UserLogged = "Alex alex" + "s" // Example name user logged
Table = functionWhichFindTablebyName(UserLogged) // Find table by name
Table.objects.get.all()
Can I do like this?I want that use for 'box mail users'.I have a lot of table and I don't wanna write manual in import/from.
I feel that this reflects a poorly implemented thing that needs a second though. It sounds like you are creating a table for each user, and storing there the messages for that user, when you should create a table Message related to User. That being said, if you want to retrieve an object (a table) from a module:
from any_app import models
getattr(models, "AlexAlex").objects.all()
Django also offers ContentTypes, which allows you to do the things you ask for without having to import the models. E.g.
from django.contrib.contenttypes.models import ContentType
obj = ContentType.objects.get(app_label="any_app", model="alexalex")
obj.model_class().objects.all()
# Or p.get_all_objects_for_this_type(kwargs)

dajngo-admin-sortable2 doesn't sort order of SortableAdminMixin

I created an app with django and python3 containing several tutorials, which in turn contain multiple content entrys that are saved in another table. Each tutorial is represented by an entry in the exercises tutorial model. I want to be able to sort the tutorials and the contents in the django admin panel. It works fine for the inline tutorial contents with SortableInlineAdminMixin class. It also works fine if I create new tutorials from scratch without having any objects saved before (it works local on my pc if I clone this project and set it up from scratch)
My problem now is, that I have the app setup like you see in the code and pictures below on a ubuntu server with apache, but I can't sort the tutorials (the inline contents still work fine). If i drag and drop them to a new position and reload, they don't save at their new position and fall back to their old position.
Tutorial and TutorialContent model:
from django.db import models
from ckeditor_uploader.fields import RichTextUploadingField
# Page for tutorials
class Tutorial(models.Model):
title = models.CharField(max_length=60)
order = models.PositiveIntegerField(default=0, null=False, unique=True)
# Timestamp
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['order']
def __str__(self):
return self.title
# Content for tutorials
class TutorialContent(models.Model):
lesson_page = models.ForeignKey(Tutorial, related_name='tutorial_content', on_delete=models.CASCADE)
content = RichTextUploadingField()
order = models.PositiveIntegerField(default=0, null=False)
# Timestamp
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['order']
def __str__(self):
description = 'Order - ' + str(self.order)
return description
Tutorial and TutorialContent admin:
from django.contrib import admin
from .models import Tutorial, TutorialContent
from adminsortable2.admin import SortableInlineAdminMixin, SortableAdminMixin
class TutorialContentInline(SortableInlineAdminMixin, admin.TabularInline):
model = TutorialContent
class TutorialAdmin(SortableAdminMixin, admin.ModelAdmin):
model = Tutorial
inlines = [TutorialContentInline]
list_display = ['title']
admin.site.register(Tutorial, TutorialAdmin)
Django admin tutorial model panel:
SQLite3 view of the corresponding table:
Maybe a little to late, but:
If there is already some model instance persisted in your db when you add the adminsortable2 field in your model, the ordering will not works, you need to build the order a first time with:
python manage.py reorder your_app.YourModel
Source: https://django-admin-sortable2.readthedocs.io/en/latest/usage.html#initial-data
Hoping this can help.

Transform Flask REST API into Django app

I am struggling on porting my (functional) Flask REST API into a working Django APP. I have researched but could not find solution to my problem.
It is for a movie recommendation system (based on MovieLens dataset).
Basically I want to move from this architecture:
Flask API to this one: Django app
The Flask API is quite straightforward and works well when I test it with Postman:
from flask import Flask, jsonify, request
from movieEngine import MovieRecommender
import sqlite3
app = Flask(__name__)
#app.route('/prediction/<int:userId>',methods=['GET'])
def get(userId):
result = recommendation_engine.predictInterest(userId)
return jsonify(result)
#app.route('/add',methods=['POST'])
def add():
userId = request.json['userId']
movieId = request.json['movieId']
rating = request.json['rating']
result = recommendation_engine.addData(userId,movieId,rating)
return jsonify(result)
if __name__ == '__main__':
global recommendation_engine
global database
database = './data/RecommenderSystem.db'
sqlconnector = sqlite3.connect(database,check_same_thread=False)
recommendation_engine = MovieRecommender(sqlconnector)
app.run(debug=True)
In Django, I have already setup the main Models.py:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=256, null=True)
def __str__(self):
return self.name
class Movie(models.Model):
title = models.CharField(max_length=256)
def __str__(self):
return self.title
class Rating(models.Model):
user = models.ForeignKey(User)
movie = models.ForeignKey(Movie)
rating = models.FloatField()
timestamp = models.DateTimeField(auto_now=True)
def __str__(self):
return 'User {:} rated movie {:} --> {:}/5 '.format(self.user,self.movie,self.rating)
class Recommendation(models.Model):
user = models.ForeignKey(User)
top5 = models.CharField(max_length=256)
def __str__(self):
return 'Recommendation for user {:}'.format(self.user)
The value stored in the recommendation table is simply a string containing a list of 5 movie IDs.
Any idea on how to turn this string into an actual list of 5 movie names?
All suggestions and ideas will be very much appreciated :)
The value stored in the recommendation table is simply a string containing a list of 5 movie IDs.
That's very bad design. You want an ordered many to many relationship between User and Movie.
Any idea on how to turn this string into an actual list of 5 movie
cf above.
I have now modified my 'Models.py'
class Recommendation(models.Model):
user = models.ForeignKey(User)
topmovies = models.ManyToManyField(Movie)
So I have a many-many relationship |Recommendation|<=>|Movies|.
Later I will modify the engine to fill this recommendation table.
In the meantime, assuming the recommendation table is filled-up, how do you suggest I handle the request?
On the urls.py I know I will have to add something like:
urlpatterns = [
....,
url(regex, someView),
]
but I am lost on how to actually use the user_id posted in the request to fetch the list of recommended movies.

Setting up media path in Django to object DateField information

I am trying to setup an user-uploaded class through the backend as Django admin. I am trying to make it so the path of the ImageField is based on the user-inputted DateField information; this is what I have.
from django.db import models
from datetime import date
class Article(models.Model):
def img_date(self):
return str(self.date.year) + str(self.date.month) + str(self.date.day)
#main_title = models.
title = models.TextField(max_length=200)
date = models.DateField()
content = models.TextField()
link = models.CharField(max_length=200)
image = models.ImageField(upload_to=img_date)
However, when I submit the object, I get an error saying "img_date() takes 1 positional argument but 2 were given". I need some help figuring out how to set a manual path like I explained earlier.
Thanks,
Have a look at the FileField docs (ImageField inherits from FileField).
In particular, note that the upload_to callable must accept two arguments, the model instance, and the original file name. So your code could look something like this (I removed the date import because it was unused):
from django.db import models
def img_date(instance, filename):
return str(instance.date.year) + str(instance.date.month) + str(instance.date.day)
class Article(models.Model):
title = models.TextField(max_length=200)
date = models.DateField()
content = models.TextField()
link = models.CharField(max_length=200)
image = models.ImageField(upload_to=img_date)
I've used your example code but you'll probably want to modify it so that two articles with the same date don't use the same image path.

Django: Ordered list of model instances from different models?

Users can upload three different types of content onto our site: image, video, audio. Here are the models for each type:
class ImageItem(models.Model):
user = models.ForeignKey(User)
upload_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to=img_get_file_path)
title = models.CharFiled(max_length=1000,
blank=True)
class VideoItem(models.Model):
user = models.ForeignKey(User)
upload_date = models.DateTimeField(auto_now_add=True)
video = models.FileField(upload_to=vid_get_file_path)
title = models.CharFiled(max_length=1000,
blank=True)
class AudioItem(models.Model):
user = models.ForeignKey(User)
upload_date = models.DateTimeField(auto_now_add=True)
audio = models.FileField(upload_to=aud_get_file_path)
title = models.CharFiled(max_length=1000,
blank=True)
I have a page called library.html, which renders all the items that a user has uploaded, in order from most recently uploaded to oldest uploads (it displays the title and upload_date of each instance, and puts a little icon on the left symbolizing what kind of item it is).
Assuming it requires three separate queries, how can I merge the three querysets? How can I make sure they are in order from most recently uploaded?
As an alternative, you can use multi-table inheritance and factor common attributes into a superclass model. Then you just order_by upload date on the superclass model. The third-party app django-model-utils provides a custom manager called Inheritance manager that lets you automatically downcast to the subclass models in your query.
from model_utils.managers import InheritanceManager
class MediaItem(models.Model):
objects = InheritanceManager()
user = models.ForeignKey(User)
upload_date = models.DateTimeField(auto_now_add=True)
title = models.CharFiled(max_length=1000,
blank=True)
class ImageItem(MediaItem):
image = models.ImageField(upload_to=img_get_file_path)
class VideoItem(MediaItem):
video = models.FileField(upload_to=vid_get_file_path)
class AudioItem(MediaItem):
audio = models.FileField(upload_to=aud_get_file_path)
Then, your query is just:
MediaItem.objects.all().order_by('upload_date').select_subclasses()
This way, you get what you want with one just query (with 3 joins). Plus, your data is better normalized, and it's fairly simple to support all sorts more complicated queries, as well as pagination.
Even if you don't go for that, I'd still use abstract base class inheritance to conceptually normalize your data model, even though you don't get the database-side and ORM benefits.
attrgetter can be used to pull out attributes of objects that you may want to key a sort by.
from operator import attrgetter
results = []
results.extend(list(AudioItem.objects.filter(...)))
results.extend(list(VideoItem.objects.filter(...)))
results.extend(list(ImageItem.objects.filter(...))
results.sort(key=attrgetter("upload_date")
Referencing the question, this is the exact solution I used. Influenced by monkut's answer and the top answer from Frantzdy's link in his comment (thanks guys).
from itertools import chain
from operator import attrgetter
images = ImageItem.objects.filter(user=user)
video = VideoItem.objects.filter(user=user)
audio = AudioItem.objects.filter(user=user)
result_list = sorted(chain(images, video, audio),
key=attrgetter('upload_date'),
reverse=True)

Categories

Resources