Create a User with Model Bakery - django-models

I would like to create a Person instance with Model Bakery. My Person model looks like this:
User = get_user_model()
class Person(models.Model):
user = models.OneToOneField(User, related_name="friend", on_delete=CASCADE)
country = models.CharField(max_length=100)
My baker_recipes.py looks like this:
from model_bakery.recipe import Recipe
User = get_user_model()
test_user = User(username="test_user")
person = Recipe(Person, user = test_user)
My tests.py looks like this:
import pytest
from model_bakery import baker
#pytest.mark.django_db()
class TestPerson:
def setup(self):
self.person = baker.make_recipe("company.tests.person")
def test_country_access(self):
assert True
But when I run pytest with this set up I get the following error:
django.db.utils.IntegrityError: insert or update on table "company_person" violates foreign key constraint "company_person_user_id_4f1cc5d0_fk_auth_user_id"
DETAIL: Key (user_id)=(411) is not present in table "auth_user".

import pytest
from model_bakery import baker
#pytest.mark.django_db()
class TestPerson:
def setup(self):
# replace this
self.person = baker.make_recipe("company.tests.person")
# with this
self.person = baker.make(Person, ...optional_field_params)
def test_country_access(self):
assert a_condition_is_true
# assert True is not logical here so comented out
N.B with baker.make the created instance is persisted to the test db on setup with baker.prepare on the other hand it is not persisted.

Related

Blueprints and the User model

I recently started playing with flask and to do so I have been developing a little sandbox web app that will serve as a container for other projects I have in mind. So far I focused on implementing a user system and I everything seems to be working. I also implemented my version of user roles control.
Now I want to start to develop the other aspects of the web app. Let's say, for example, I want to develop a blog, my own image storage, an achievement system for a group of my friends, etc. My intention is to use the same User model for all of the sub applications and I've been trying to draw how such relationship would look like, but I haven't thought of anything different then adding all of them into my main User class. My concern is that by doing so the User class will end up being too big, with many relationships attached; besides, not every user will have access/need for each of the sub applications.
Is there a better way to 'link' my user with other sub applications?
File structure
-- MyApp
-- auth_blueprint
-- forms.py
-- routes.py
-- models.py
-- utils.py
-- achievements_blueprint
-- forms.py
-- routes.py
-- models.py
[static, templates, etc]
User Class
from myapp import db, login_manager
from flask_login import UserMixin
from flask import url_for
from random import randint
from os import listdir
__PROFILE_PICS_PATH = 'myapp/static/media/img/profile_pics/'
def new_profile_pic():
pics = listdir(__PROFILE_PICS_PATH)
if '.DS_Store' in pics:
pics.remove('.DS_Store')
n_pics = len(pics)
return '/static/media/img/profile_pics/'+ str(randint(1, n_pics)) +'.png'
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# Define a base model for other database tables to inherit
class Base(db.Model, UserMixin):
__abstract__ = True
id = db.Column(db.Integer, primary_key=True)
date_created = db.Column(db.DateTime, default=db.func.current_timestamp())
date_modified = db.Column(db.DateTime, default=db.func.current_timestamp(),
onupdate=db.func.current_timestamp())
# Define a User model
class User(Base):
__tablename__ = 'users'
first_name = db.Column(db.String(20), nullable=False, default='First Name')
last_name = db.Column(db.String(30), nullable=False, default='Last Name')
email = db.Column(db.String(120), unique=True, nullable=False)
username = db.Column(db.String(20), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
image_file = db.Column(db.String(20), nullable=False, default=new_profile_pic())
# Define the relationship to Role via UserRoles
roles = db.relationship('Role', secondary='user_roles')
def __repr__(self):
return f"User('{self.username}','{self.email}','{self.image_file}')"
def has_roles(self, role_names):
return len([role for role in self.roles if role.name in role_names])
# Define the Role data-model
class Role(Base, db.Model):
__tablename__ = 'roles'
name = db.Column(db.String(50), unique=True)
# Define the UserRoles association table
class UserRoles(Base, db.Model):
__tablename__ = 'user_roles'
user_id = db.Column(db.Integer(), db.ForeignKey('users.id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))
If I were to add, for instance, a mini blog This is what I would do:
-- MyApp
-- blog_blueprint
-- forms.py
-- routes.py
-- models.py
[etc]
1. Create the necessary models at blog_bluprint/models.py
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
2. And then add the relationship to the User model
posts = db.relationship('Post', backref='author', lazy=True)
Thanks for any help!

Google App engine: No key_name attribute

I'm trying to learn how the GAE, most things are working, but for some strange reason, this code outputs a
AttributeError: 'User_Account' object has no attribute 'key_name'
Here's the two code extracts that are relevant:
class User_Account(ndb.Model):
name = ndb.StringProperty()
firstname = ndb.StringProperty()
class AddUser(webapp2.RequestHandler):
def get(self):
test_user = User_Account(name = "snow", firstname ="jon", key_name="jon")
I've tried it with db and ndb model, it doesn't work either way...
Thanks in advance for any answer.
UPDATE: Here's the "full" code (i removed all the other un-necessary parts):
import webapp2
import cgi
from google.appengine.ext import ndb
MAIN_PAGE_HTML = """\
<html>
<body>
<br/>
Add a user
</body>
</html>
"""
class Comment(ndb.Model):
content = ndb.StringProperty()
class User_Account(ndb.Model):
name = ndb.StringProperty()
firstname = ndb.StringProperty()
comments = ndb.KeyProperty(repeated=True)
class AddUser(webapp2.RequestHandler):
def get(self):
test_user = User_Account(name = "jon", firstname ="snow", key_name="jon")
self.response.write(test_user.key_name + "<br/>")
test_user.put()
self.response.write("User added")
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.write(MAIN_PAGE_HTML)
application = webapp2.WSGIApplication([
('/', MainPage),
('/add_user', AddUser)
], debug=True)
MOAR EDIT:
Even this very simple code, when executed in the dev console, outputs an error
import os
import pprint
from google.appengine.ext import ndb
class Comment(ndb.Model):
content = ndb.StringProperty()
test_comment = Comment(content="Hello world", key_name="hello")
test_comment.put()
Please read documentation for the ndb Model class. Specifically on the model constructor arguments. https://developers.google.com/appengine/docs/python/ndb/modelclass#Constructor
You will see it takes id, rather than key_name. key_name is a constructor argument for db api.
I had a solution to a similar case where I wanted the key_name of an entity (which had key_name only and no ID). I was able to find the key_name from the property self.key().name()

NameError: name 'u1' is not defined

I am trying to follow django tutorial but with my own task.
Models.py file looks like
from django.db import models
class User(models.Model):
nickname = models.CharField(max_length=30)
password = models.CharField(max_length=30)
email = models.EmailField()
reg_date = models.DateField()
class Question(models.Model):
head = models.CharField(max_length=50)
content = models.TextField()
author = models.ForeignKey(User)
date = models.DateField()
class Answer(models.Model):
content = models.TextField()
question = models.ForeignKey(Question)
author = models.ForeignKey(User)
date = models.DateField()
validity = models.BooleanField()
I made "python manage.py shell" and wrote something like:
>>> u1 = User(nickname='Alex', password='123', email='alex#mail.ru', reg_date='2013-01-07')
>>> u1.save()
>>> u2 = User(nickname='Kate', password='abcde', email='kitten#mail.ru', reg_date='2012-12-15')
>>> u2.save()
User_list gave me
[<User: User object>, <User: User object>]
But then I made a quit and did some changes in the code. After this I cannot make u1.delete() or u2.delete() because it tells NameError: name 'u1' is not defined, but still shows me list of two users there. I can also create new u1 and u2 and delete them. How can I apply to those previous users now to clear database?
If you want to delete all User rows:
User.objects.all().delete()
If you want to find and delete the two your code created:
User.objects.get(nickname='Alex').delete()
User.objects.get(nickname='Kate').delete()

How to create an entity of a model with referenceProperty without the reference exists?

I have two model classes Team and Student. Each Team entity has more than one Users entities, I think "one to many" is a proper model. I code like this:
class Team(db.Model):
teamNmae = db.StringProperty(required=True)
teamID = db.IntegerProperty(required=True)
class Users(db.Model):
name = db.StringProperty(required=True)
reference = db.ReferenceProperty(Team,collection_name=teamMembers)
Follow this document, I need to first create a Team entity, then create Users whose reference is set to this Team entity. But,here is the problem, I want to create User first, then User can create a Team. So, how to set reference when I create a User that no Team exists ?
EDIT1:
I write simple code to test if I can create a entity without its reference entity created.
_author__ = 'Steven_yang'
import os
import webapp2
from google.appengine.ext import db
from google.appengine.ext.webapp import template
defaultStu = [
'qingWANG',
'stevenYANG',
'jingZHU',
'conghuiHE',
'lianDUAN',
'xinHAO'
]
class Students(db.Model):
#reference = db.ReferenceProperty(Team,collection_name='teamMember',required=False)
name = db.StringProperty(required=True)
class Team(db.Model):
teamName = db.StringProperty(required=True)
teamID = db.IntegerProperty(required=True)
def createStu():
stu_count = Students.all().count(1)
if stu_count == 0:
for stu in defaultStu:
newStu = Students(name = stu)
newStu.put()
class testReferenceHandler(webapp2.RequestHandler):
def get(self):
createStu()
self.render_page()
def render_page(self):
stus = Students.all().fetch(10)
templateValues={}
templateValues['stus'] = stus
form = os.path.join(os.path.dirname(__file__),'template/testref.html')
renderForm = template.render(form,templateValues)
self.response.out.write(renderForm)
app = webapp2.WSGIApplication([('/testref',testReferenceHandler)],debug=True)
HTML file is:
<body>
{% for s in stus%}
<div>{{s.name}}</div>
{% endfor%}
</body>
</html>
when I comment out the ReferenceProperty line, everything is fine. When I add the ReferenceProperty line, I got a server error. So, I can't create a entity without its reference created before?
Did you try to set reference to Team model as None when creating a User instance?
Also change the last line your code snippet to:
reference = db.ReferenceProperty(Team,required=False)
i.e. add required=False. This is what is suggested in this answer.

Relationships in Django Admin

I get really confused with many-to-many database relationships, so can some one please clarify how I would achieve this?
I need a table of "Tags" (as in tag words) and a table for "Entries", such at many "Entries" could correspond to many Tag words.
Right now I have my models like this:
# models.py
class Tags(models.Model):
tag = models.CharField(max_length=255)
entry = models.ManyToManyField(Entry)
class Entry(models.Model):
entry = models.CharField(max_length=255)
description = models.TextField()
Now I'm confused, how would I setup my admin.py so I could then add tags when I create a new entry?
What you need is using the through feature of models:
class Tag(models.Model):
tag = models.CharField(max_length=255)
entry = models.ManyToManyField(Entry, through='TaggedEntries')
class Entry(models.Model):
entry = models.CharField(max_length=255)
description = models.TextField()
class TaggedEntries(models.Model):
entry = models.ForeignKey(Entry)
tag = models.ForeignKey(Tag)
and now use that model in your admin:
class TagsInline(admin.TabularInline):
model = TaggedEntries
extra = 1
class EntryAdmin(admin.ModelAdmin):
inlines = (TagsInline, )
admin.site.register(Entry, EntryAdmin)
admin.site.register(Tag)
You will need something along the lines of:
# admin.py
from django.contrib import admin
from models import *
class TagsInline(admin.TabularInline):
model = Tag
extra = 1
class EntryAdmin(admin.ModelAdmin):
inlines = (TagsInline, )
admin.site.register(Entry, EntryAdmin)
admin.site.register(Tag)
(Note, this code was written in a browser!)

Resources