Transform Flask REST API into Django app - python

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.

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)

How to connect models from different apps in Django?

I have a few apps within my Django project. There are two apps that I am currently working with "Application" and "User" and I have two questions related to models:
Question 1:
I want to design it in such a way so that external users submit their contact form on Application/templates/Application/Apply.html and the info would get added to the database. Internal users would be able to add external users as well but from a different template: User/templates/User/AddNewContact.html
I am able to add a new contact from an internal user's perspective:
User/models.py
class Contact(models.Model):
ContactName = models.CharField(max_length = 250, default='')
ContactResidence = models.CharField(max_length = 250, default='')
Tel = models.CharField(max_length = 250, default='')
def get_absolute_url(self):
return reverse('User:ContactDetails', kwargs={'pk': self.pk}
)
def __str__(self):
return self.ContactName
class Locations(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
Country = models.CharField(max_length=250, default='')
def __str__(self):
return self.Country
I was going to just copy this model and paste it into Application/models.py but there are two problems:
1) I don't want external users to be directed to URL: User:ContactDetails and technically, it is not going to work out because I will build the authentication later on.
2) I feel that by copying and pasting I am breaking the 'don't repeat yourself" rule.
Should I connect two models using the foreign keys? What are the best practices in this case?
Question 2
Am I working with one-to-many relationship according to the model provided? I want to have one contact with his personal info (tel/email/address) and a number of branch locations across the world associated with that contact.
To be used a relationship one to many, you can be doing as after:
On models of father app (father table):
class Department(models.Model):
dept_id = models.AutoField(primary_key=True)
On models of child app (child table):
from appname.models import Department
class Office(models.Model):
office_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
dept = models.ForeignKey(Department, on_delete=models.CASCADE)
It helped me.
Question 1: Well, you don't need to copy paste the model. You can use models from other django apps anytime, just need to import it. Basically what you should do is, instead of linking the url directly to the template in the Applications app, you should connect it to a view. In the view file you can import the models from User.models import *, and use them normally.
Question 2: As far as I understand the question your structure provides what you want: one contact (with personal info) associated with several countries. Except that you should replace Agent by Contact in contact = models.ForeignKey(Agent, on_delete=models.CASCADE)
Question 1: Note that the 'get_absolute_url' method is only called if you don't provide a success url in your view. If you are using a CreateView or FormView you can specify the success url by overriding the get_success_url method, for example:
class ContactCreateView(CreateView):
model = Contact
fields = ['ContactName', 'ContactResidence', 'Tel']
def get_success_url(self):
if not self.request.user.internal: # e.g. internal is a User bool field
return HttpResponseRedirect('some/external/url/')
return super().get_success_url() # call get_absolute_url model method.
The DRY principle is respected.
Question 2: Yes, the question you need to ask yourself is 'does a model instance (In this case Contact) have many instances of another model (Location)?' If the answer is yes, then the M2M field should go into your Contact model. See the django docs explaining the pizza/toppings example.
The apps should be in the same project and you can import one model as:
import appName.models or
from appName.models import ClassName
In app2 models you can use foreignKey or manyTomany after importing the class:
from appsName.models import ClassName
class Person(models.Model):
con = ForeignKey(ClassName)

Django no such column ForeignKey

I'm doing a Django project (kind of social network) and want to have a page where I can see all my posts, which I did.
I allways get the error: no such column: uploaded_by
in models.py
from django.db import models
from django.contrib.auth.models import User
class ContentItem(models.Model):
upload_date = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=100, default='no title')
description = models.CharField(max_length=400, default='no description')
image = models.ImageField(upload_to='image_board/posts/', default='null')
uploaded_by = models.ForeignKey(User, default='0')
def __str__(self):
return self.title
in views.py
def view_my_favorites(request):
all_posts = ContentItem.objects.raw('SELECT * FROM image_board_ContentItem WHERE uploaded_by = request.user.username')
template = loader.get_template('favorites.html')
context = {
'all_posts': all_posts,
}
return HttpResponse(template.render(context, request))
I want to get the user name of the user who is loged in, how can i whrite this in the sql query?
Thaks guys :)
Your actual issue is probably caused by neglecting to make and run migrations after adding the uploaded_by field.
But there are a huge number of other things wrong here.
Firstly, you are comparing the uploaded_by column with a non-existent column, request.user.username. You need to use the actual value of that variable.
Secondly, you are comparing a foreign key - uploaded_by - with a string, username. These will never match.
Thirdly, you are using a raw query. There is absolutely no need to do that here.
Your query is trivial to express in the Django query syntax. You should do:
all_posts = ContentItem.filter(uploaded_by=request.user)
or even simpler:
all_posts = request.user.contentitem_set.all()

Consuming Django Rest Api in the same project

I'm pretty new to django's rest framework and I built my first example API using the official tutorial here. But I have no idea how to consume this API's data into another app in the same project such its data can be rendered into HTML.
Suppose I create an API students for students(with their details) in a school. Now how do I use this API in the same project to display the number of students in schools and their details.
Most of the tutorials or explanations online are for third-party API's and I can't figure out how to proceed. Thanks in advance.
models.py
class Test(models.Model):
date = models.DateTimeField(auto_now_add=True)
test_name = models.CharField(max_length=200,default='simple blood test',blank=False)
subject = models.CharField(max_length=100,default='')
def __str__(self):
return self.test_name
class Person(models.Model):
tests = models.ManyToManyField(Test)
title = models.CharField(max_length=3,default="mr",blank=False)
name = models.CharField(max_length=50,default='',blank=False)
def __str__(self):
return self.name
views.py
class PersonList(generics.ListCreateAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class PersonDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
serializers.py
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = Test
fields = ('test_name','subject')
class PersonSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
tests = TestSerializer(many=True, read_only=True)
class Meta:
model = Person
fields = ('url','id','name')
This is my API definiton. I want to create another app to display data such list of all students and details about them etc.
You will have to hit your endpoints in your consuming view, the easiest way to do this is with the requests library. First install the library:
pip install requests
Then use it in your consuming view:
def consumer_view(request):
response = requests.get('http://your-url.com/your-endpoint')
# do what you need to do here
You can use response.json() to get the JSON response form your API as a Python dictionary. If you are just using ./manage.py runserver your URL will be:
http:localhost:8000/your-endpoint
or
http://192.168.0.1:8000/your-endpoint
This way of consuming an API is somewhat redundant if you are working completely within Django. It's often much easier to use the ORM in these cases. However if you are making the API to be available for outside use (either publicly or via API keys) then this approach makes sense.

Correct Model structure for django app?

I have a blog app that consists of 3 models: department, author, post
I am having trouble structuring the models correctly and creating the corresponding forms
models.py
from django.db import models
class Department(models.Model):
name=models.CharField(max_length=20)
posts = models.ForeignKey('Post')
authors = models.ManyToManyField('Author')
def __unicode__(self):
return self.name
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
post = models.ForeignKey('Post')
def __unicode__(self):
return self.last_name
class Post(models.Model):
title=models.CharField(max_length=20)
post = models.TextField()
creation_date = models.DateField(auto_now_add=True)
def __unicode__(self):
return self.title
The idea is that a department can have many posts, but each post belongs to only one department. A department can also be made up of multiple authors and authors can be in multiple departments. Where I'm really having trouble is with the forms.
The relevant urls.py looks like this:
url(r'^(?P<department_id>\d+)/posts/$', views.posts, name='posts'),
url(r'^(?P<department_id>\d+)/add_post/$', views.add_post, name="add_post"),
So I can pull in all the posts by department. The goal of the form is for the department id to be recognized and added automatically to the post.
def add_post(request, department_id):
department = Department.objects.get(pk=department_id)
if request.method == 'POST':
new_post_form = PostForm(data=request.POST)
if new_post_form.is_valid():
new_post = new_post_form.save(commit=False)
new_post.department = department
new_post.save()
return redirect('posts', department_id=department_id)
Now I realize that the Post model does not have a department attribute, which is the error that I get, but I'm guessing that there's a way to make this happen, I just don't know what it is.
Thanks as always for your help. Please let me know if anything is unclear.
The fact that the Post model does not have a department attribute should have given you the clue that your structure is wrong: it clearly needs one. The issue is that you have your ForeignKey the wrong way round: a FK is a one-to-many relationship, and lives on the "many" side, in your case Post, pointing to the "one", ie the Department.
Then your view code will work exactly as it is, and you can retrieve all posts for a department with my_department.post_set.all().

Categories

Resources