How to create factory column for self referential column in a model in pytest? - pytest

I have a model with a column which is a self referential foreign key.
class Foo(db.Model):
foo_ref_id = db.Column(
db.Integer,
db.ForeignKey("foo.id", ondelete="CASCADE"),
nullable=True,
index=True,
)
I am trying to create a factory model for the same model:
class FooFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = Foo
context_base_id = factory.SubFactory("tests.factories.BaseFactory", parent=None)
context_base_id = factory.LazyAttribute(lambda x: BaseFactory(parent=None))
context_base_id = factory.Trait(
parent_category=factory.SubFactory("tests.factories.BaseFactory")
)
I have tried the 3 ways of doing achieving this. All of them return an error of maximum depth of recursion exceeded.
What is the proper way of doing this?

You have to tell the factory where to stop.
The simplest option is to pass an extra parameter to the SubFactory call:
class FooFactory(factory.alchemy.SQLAlchemyModelFactory):
class Meta:
model = Foo
parent = factory.SubFactory(
'apps.foo.factories.FooFactory',
parent__parent__parent=None,
)
# Other fields here
With the code above:
The first FooFactory will set self.parent = FooFactory(parent__parent__parent=None)
The parent will set self.parent = FooFactory(parent__parent=None)
The grandparent will set self.parent = FooFactory(parent=None)
The great-grandparent will set self.parent = None, thus ending the recursion.

Related

Basic F# / Entity Framework / Generic Functions

I'm a complete beginner when it comes to development, so apologies in advance for my poor grasp of the terminology here...
I'm trying to create a number of very simple unrelated tables in a SQL database just to get my head round things. I'd like to reference these using Entity Framework, and I'd like to minimise repetition where possible. I'm trying to understand whether there is a more elegant way of doing this so that I don't have to re-write the getters and setters each time:
// First open "System; System.Data; System.Data.Entity; System.ComponentModel.DataAnnotations"
// Then define "connectionString"
// Then create two simple classes that have no relation to each other, using CLIMutable
// to help Entity Framework along.
module Model =
[<CLIMutable>] type Customer = {[<Key>]Id: int; FirstName: string; LastName: string;}
[<CLIMutable>] type Item = {[<Key>]Id: int; ItemName: string; ItemDescription: string;}
module Actions =
open Model
type Context() =
inherit DbContext()
[<DefaultValue>] val mutable customers: DbSet<Customer>
member public this.Customers with get() = this.customers
and set v = this.customers <- v
[<DefaultValue>] val mutable items: DbSet<Item>
member public this.Items with get() = this.items
and set v = this.items <- v
// I would like to be able to add several more very simple classes without having to
// repetively type out the getters and setters each time. Ideally I'd like to turn the above
// into a generic function (method? I'm not sure of terminology) that I can call later and
// pass it my desired parameters in terms of table/object names. However, if I move the code
// above the Model and replace DbSet<Customer> with DbSet<'T> this won't work since it won't
// know what type 'T is at this point. I suspect I need a generic function (method?) that
// I can create a new instance of later and replace the generics with actual values (using
// reflection?). Is there any way to do this without making Entity Framework get upset?
let db = new Context()
db.Database.Connection.ConnectionString <- Settings.connectionString
Similarly I'd like to create a generic function that does the Add() and SaveChanges() steps
below, but I'm not sure whether this is possible since I'd need to dynamically replace
'Customers' or 'Items' with a table name that I've passed in - and also the type of 't'
could vary depending on what is calling the function and I don't know whether that's allowed.
let createCustomer id firstName lastName =
let t : Customer = {Id = id;FirstName = firstName; LastName = lastName}
db.Customers.Add(t) |> ignore
db.SaveChanges() |> ignore
let createItem id itemName itemDescription =
let t : Item = {Id = id; ItemName = itemName; ItemDescription = itemDescription}
db.Items.Add(t) |> ignore
db.SaveChanges() |> ignore
open Actions
[<EntryPoint>]
let main argv =
createCustomer 1 "Bob" "Smith"
createItem 1 "First item" "First item test"
Console.ReadLine() |> ignore
0
Thanks for any help, understand my questions are probably very basic so if people can't be bothered to re-write code but are able to point me in the right direction of resources for further reading that'd be great!
[edit] Thanks very much to Fyodor for providing the solution. The key was adding the ": Context" type annotation to the "db" element when referring to it generally. Additionally I had made the silly mistake of not opening the "Model" module in my main argument. Updated and working code it as below:
module Model =
[<CLIMutable>] type Customer = {[<Key>]Id: int; FirstName: string; LastName: string;}
module Actions =
open Model
type Context() =
inherit DbContext()
member val Customers: DbSet<Customer> = null with get, set
let db = new Context()
db.Database.Connection.ConnectionString <- Settings.connectionString
let addAndCommit (db : Context) x =
db.Set().Add x |> ignore
db.SaveChanges() |> ignore
let createCustomer id firstName lastName =
addAndCommit db {Id = id; FirstName = firstName; LastName = lastName}
open Actions
open Model
[<EntryPoint>]
let main argv =
createCustomer 1 "Bob" "Smith"
Console.ReadLine() |> ignore
0
First, to declare a property with a backing field, use member val:
type Context() =
...
member val Customers: DbSet<Customer> = null with get, set
...
Second, to access a DbSet of a specific type, you don't need a property. You can get it via DbContext.Set<'t> method:
let addAndCommit (db: Context) (x: 't) =
db.Set<'t>().Add x |> ignore
db.SaveChanges() |> ignore
let createCustomer id firstName lastName =
addAndCommit db {Id = id; FirstName = firstName; LastName = lastName}
But the explicit 't annotation is not really required: F# can infer it for you.
let addAndCommit (db: Context) x =
db.Set().Add x |> ignore
db.SaveChanges() |> ignore

JPA and "anonymous" classes in scala

I'm a bit stuck and don't understand what's going on.
This one doesn't work
#Entity
#DynamicInsert
#DynamicUpdate
#SelectBeforeUpdate
#Table
class Entity {
#Column(nullable = false)
var owner: String = _
}
val myEntity = new Entity() {
owner = "some owner 1"
}
session.persist(myEntity)
Hibernate throws exception:
java.lang.IllegalArgumentException: Unknown entity:persistence.dao.EntityDaoTest$$anonfun$13$$anonfun$14$$anon$5
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:777)
This one works:
val myEntity = new Entity()
entity.owner = "some owner 1"
session.persist(myEntity)
Why? Why does hibernate don't recognize my Entity instance?
UPD:
#Sheinbergon, thanks, it's clear. I completely forgot that annotations are lost. Is there any possibility to set entity fields with some shortcut?
writing
val myEntity = new MyEntity()
myEntity.owner = "some owner"
myEntity.someOtherProperty = "value"
is super boring
One more question
This one works:
val parent = new Parent
parent.owner = "Our parent"
parent.addChild(new Child() {
name = "First parent's child"
addGrandChild(new GrandChild() {
name = "Grand child name"
addGrandGrandChild(new GrandGrandChild() {
name = "Grand Grand child name"
address = new Address() {
id = 1L
}
})
})
})
Why? Child, GrandChild, GrandGrandChild also created anonymously.
addChild, addGrandChild, addGrandGrandChild are just list mutators.
def addChild(child: Child): Unit = {
if (children == null) {
children = new util.ArrayList[Child]()
}
if (Option(child.parent).isEmpty) {
child.parent = this
}
children.add(child)
}
What you are doing here is instantiating a class anonymously in Scala , and well... that creates an anonymous implementation of your class Entity ( like instantiating an interface anonymously in Java).
you can see it by printing the class name - println(myEntity.getClass) in both cases
Annotations applied to the original class do not apply to the anonymous one (reflection can still find them in the super class, but that's up to the code scanning them) and I guess that's why you're getting the various JPA exceptions
In response to your added sub-questions
Regarding a shortcut - why don't you use companion objects for factories or turn this class into a case class (with defaults), allowing for nicer, more flexible initialization.
Regarding the second object graph(and assuming eachof your classes are annotated) - again it depends on how the reflective code treats the objects it scans. it's possible ( and more likely, given that it won't scan each member of the collection for annotations ) it takes annotation definitions from the erased type ( possible to get it's FQDN class name as ParameterizedType in Java's reflection API) of the collection and not from the actual members of the collection and that's why it works.
I'm not really sure what it does about field definitions though (they are only present in the "super" class), but there's no "magic" here, just plain old reflection scans.

Linq projection: Get reference of new projected entity

I need to map EF entities to respective DTO. In the example below I have EF entities Parent and Child, and Child entity contains reference to Parent object. I also have ParentDto and ChildDto (DTO), and ChildDto contains reference to ParentDto (not Parent). So, how can I assign ParentDto reference to ChildDto instance in below method:
public Task<List<ParentDto>> Method()
{
return (Context.Set<Parent>()
.Where(someCondition)
.Select(p => new ParentDto
{
// here we map all properties from Parent to ParentDto
... ,
Children = p.Children.Select(c => new ChildDto
{
// here we map all properties from Child to ChildDto
... ,
Parent = ? // reference to newly created ParentDto instance
})
}).ToListAsync();
}
You have to use a variable but you can't do it in a lambda expression. You have to do the mapping in memory after calling ToListAsync():
public Task<List<ParentDto>> Method()
{
var parents = await (Context.Set<Parent>()
.Where(someCondition)
.ToListAsync());
return parents.Select(p =>
{
var parent = new ParentDto();
//map parent properties
parent.Children = p.Children.Select(c => new ChildrenDto
{
//map child properties
});
return parent;
}).ToList();
}
In regular LINQ (not to entities) this isn't possible because of an important feature of object initializers: atomic assignment. As you can read here, an object initialization like...
var c = new Customer() { Name = "Bart", City = "Redmond", Age = 24 };
...is equivalent to...
Customer __t = new Customer();
__t.Name = "Bart";
__t.City = "Redmond";
__t.Age = 24;
Customer c = __t;
So the object is created and fully initialized first and then its reference is exposed. Therefore, if inside the object another object is initialized, the nested object will never be able to grab a reference to its parent during the initialization phase. You can only assign the parent afterwards.
Although in LINQ-to-entities the mechanism of creating objects is entirely different, the initialization logic can be considered identical, and the same restrictions apply.
As you know, in LINQ-to-Entities we can't call instance methods of entities while we're in the query expression. Else you could, for instance, have called some method in Parent that constructs its children (and assigns itself to it as their parent). As it is now, the only thing you can do is construct the Parents with their nested parent.Children first and after that, traverse the parent.Children collections and assign their Parent to them (as in Ufuk's answer).

tastypie - List related resources keys instead of urls

When I have a related Resource, I would like to list foreign keys, instead of a url to that resource. How is that possible aside from dehydrating it?
I'm not sure that it's possible without dehydrating the field. I usually have utility functions that handle conversion the dehydration of foreign key and many-to-many relationships, something like this:
#api_utils.py
def many_to_many_to_ids(bundle, field_name):
field_ids = getattr(bundle.obj, field_name).values_list('id', flat=True)
field_ids = map(int, field_ids)
return field_ids
def foreign_key_to_id(bundle, field_name):
field = getattr(bundle.obj, field_name)
field_id = getattr(field, 'id', None)
return field_id
And apply them to the fields like so:
#api.py
from functools import partial
class CompanyResource(CommonModelResource):
categories = fields.ManyToManyField(CompanyCategoryResource, 'categories')
class Meta(CommonModelResource.Meta):
queryset = Company.objects.all()
dehydrate_categories = partial(many_to_many_to_ids, field_name='categories')
class HotDealResource(CommonModelResource):
company = fields.ForeignKey(CompanyResource, 'company')
class Meta(CommonModelResource.Meta):
queryset = HotDeal.objects.all()
dehydrate_company = partial(foreign_key_to_id, field_name='company')

How do insert more than one row into a table using Entity Framework when one column is a foreign key?

Please help me. I can't find this anywhere. I want to do this with Entity framework when inserting:
Add 1 row to table tParent
Add 4 rows to table tChildren.
tChildren has a column that is a FK of tParent called ParentID.
I'm on 4.0 framework.
You will have to add the children to the parent using a loop but need to call save changes once, something like as follows, say the parent is Order and child is called OrderItem
public void AddOrder(OrderDto orderToAdd)
{
var newOrder = Order.CreateOrder(orderToAdd.OrderID, .....); //set all other non nullable attributes
neworder.OrderDate = orderToAdd.OrderDate;
//set other properties
'
'
//then add the order items to the newOrder
//note orderToAdd.OrderItemsDto is the ChildList
foreach (OrderItemDto o in orderToAdd.OrderItemsDto)
{
var orderItem = OrderItem.CreateOrderItem(orderToAdd.OrderID, o.OrderItemID); //set all other non nullable attributes
orderItem.OrderQuantity = o.OrderQuantity;
//set other properties
'
'
newOrder.OrderItems.Add(orderItem);
}
context.AddToOrders(newOrder);
context.SaveChanges();
}
The key is that you have navigational properties setup on the entities.
tParent should have a navigational property called tChildrens, and (optionally), tChildren should have a navigational property called tParent.
The multiplicity should be tParent 1..* tChildren.
With that in mind, this should do the trick:
var parent = new tParent();
var child1 = new tChild();
var child2 = new tChild();
// set properties you need, etc etc
parent.tChildrens.Add(child1);
parent.tChildrens.Add(child2);
context.SaveChanges();
EF is smart enough to add the parent, grab the identity, then insert the children with the FK set to the identity just created.